Compare commits
256 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1e8214cd3f | |||
| 7802257700 | |||
| 60031bed47 | |||
| d7e795a731 | |||
| c0cccd6196 | |||
| 6cd0d5d779 | |||
| f66d8f98c9 | |||
| a94a3e9741 | |||
| c798242bfe | |||
| 80622d4037 | |||
| 5ac2eed3d9 | |||
| 33ec757c41 | |||
| b6c84d19ab | |||
| f91849ec4b | |||
| 46ae6e1c2a | |||
| 7cbf7af6e8 | |||
| 7f69f5937a | |||
| e0ad859eef | |||
| f5a2641ea1 | |||
| ccaff85870 | |||
| af65e40986 | |||
| f41e3c01f4 | |||
| e8b97a12a9 | |||
| 8744f6bd7f | |||
| 204f4eefd8 | |||
| 7af193df77 | |||
| b082a6f1da | |||
| ce1e5b5ae1 | |||
| 565360a3f2 | |||
| 69cec874a1 | |||
| 66206e8dd7 | |||
| 44c1879e27 | |||
| a9bb95fefd | |||
| 4ad2242e96 | |||
| 1e1e333d61 | |||
| 81efdd41f4 | |||
| ac245b39d5 | |||
| cecfaaf63e | |||
| 8d37bb4469 | |||
| b710f2d69f | |||
| d96646b0e0 | |||
| c069efaa1b | |||
| 25b12eb38a | |||
| 6779559ba2 | |||
| 4e411eab59 | |||
| 1ba9ce283b | |||
| bd191af41b | |||
| 13f4f7ffdd | |||
| db62588d47 | |||
| 17325c7939 | |||
| e275e7614e | |||
| d383b1e1a3 | |||
| 973579f462 | |||
| 05db38225a | |||
| 3b771656bb | |||
| fe531960ab | |||
| accbc5d809 | |||
| fa5b74b763 | |||
| 124cdfda37 | |||
| 8ad3d01d81 | |||
| 448baac0f4 | |||
| e225d77146 | |||
| 74a2d9486b | |||
| 6b74aa2673 | |||
| 9f4a0fedbf | |||
| 9b079b371d | |||
| 1439dace83 | |||
| 44a6ac4c2a | |||
| 08826398af | |||
| 5fccfc65ec | |||
| 91d64a8871 | |||
| b9e92ba9fa | |||
| d88078aa28 | |||
| 188b952621 | |||
| 804a8bb853 | |||
| ab229ac261 | |||
| ff2bbb7a31 | |||
| c8fb0994ed | |||
| fd13f41294 | |||
| 4b15d30c2a | |||
| 076d862ee0 | |||
| f7d66c8b50 | |||
| 1ef25b356c | |||
| 7e06892ad7 | |||
| f1ccb85658 | |||
| a08b3ee882 | |||
| f0fafa3ba7 | |||
| 9c1feb24e6 | |||
| f4aa80e6b4 | |||
| 14d22d29b1 | |||
| 666e8c2f2f | |||
| 4a462f3c9a | |||
| 789cfea682 | |||
| ead8daf26c | |||
| 2dfb82d5b9 | |||
| 83bcbb8299 | |||
| d85f48fb97 | |||
| e4660b8608 | |||
| 96141d82f4 | |||
| ef17dc10ca | |||
| caca5ffa12 | |||
| e08d3858be | |||
| 0e063b9759 | |||
| 6dbdef9d57 | |||
| 81c58d9727 | |||
| 54701e0c46 | |||
| 069417499f | |||
| 5aec670621 | |||
| 16e9f168b9 | |||
| 8897c3d4cb | |||
| 48a520708b | |||
| 4a142f35f5 | |||
| a30bb7db20 | |||
| 61842b4bcb | |||
| 0cae01772c | |||
| 6a95c11cf9 | |||
| 401567f852 | |||
| 475326691d | |||
| a63b02ab69 | |||
| 2ff824e631 | |||
| e866b2231f | |||
| 451487ef80 | |||
| 4d64bd7e66 | |||
| 2e21de073d | |||
| 8675f378b6 | |||
| 238a369948 | |||
| 7db6c25c6a | |||
| bcbc59f04e | |||
| 1f1f03eaf4 | |||
| c9a1173698 | |||
| 3ba4cd5919 | |||
| 2c9f6b28f7 | |||
| 79aff4c12d | |||
| 40fddf1715 | |||
| 9005e50049 | |||
| dc7493e283 | |||
| 8f65fc1ab7 | |||
| 3d732625a7 | |||
| 5f678d10cb | |||
| 2a55ac04ce | |||
| 2feb5a47ac | |||
| 27deeccdb3 | |||
| c7f12f3a74 | |||
| 99f0f0120b | |||
| 34070f0b93 | |||
| f300b31d8d | |||
| bc5f9fb0a3 | |||
| 7371c219b1 | |||
| d5dd445a06 | |||
| b7f0187e9c | |||
| e982426885 | |||
| 6447666284 | |||
| ea4fcebf33 | |||
| 94f7d49522 | |||
| bbf2938719 | |||
| df9db96bd1 | |||
| 4d45677160 | |||
| 2981596fc3 | |||
| ecce4d6578 | |||
| bf52b5eb06 | |||
| d8baf6d1e8 | |||
| 4322931d97 | |||
| ad4bf703f0 | |||
| 342679b6d3 | |||
| 4a52be76fe | |||
| afc55d76e7 | |||
| 9e53f19b02 | |||
| 8614bca405 | |||
| 5f3bdaeebe | |||
| fd81cd2ae0 | |||
| bc6599ae51 | |||
| 6c2c174926 | |||
| 9205d0be65 | |||
| 199e274cac | |||
| c9a36d51c4 | |||
| 7bffc86777 | |||
| ce1b58d293 | |||
| 4d2b35c9ee | |||
| 47168972da | |||
| dee289e2d9 | |||
| 1fc7c7898b | |||
| dfc8a0d548 | |||
| daa0fe353b | |||
| 766b3edeee | |||
| 8e90fd0b63 | |||
| 9a00a9027d | |||
| e2a45c8f97 | |||
| ee69861fb5 | |||
| 5b97d3ee09 | |||
| 38ab492030 | |||
| 266d992017 | |||
| 0979848bdc | |||
| 3d371be0e5 | |||
| f96955b9f0 | |||
| 794d048bf2 | |||
| 595afd8964 | |||
| da8fadb203 | |||
| ca7c07e817 | |||
| bf95f93cad | |||
| 7766b08f08 | |||
| 823ac11eb3 | |||
| c5e61413a4 | |||
| df4726eb95 | |||
| 25a6da5638 | |||
| 5ddec963d0 | |||
| 597143df7f | |||
| 572082ac2b | |||
| d328e834b1 | |||
| aa540f85fa | |||
| 1084d86063 | |||
| a43d93512d | |||
| a8177201ef | |||
| 85bebf0b43 | |||
| f36feee0dc | |||
| c0bbc2216e | |||
| 8ce23f15e8 | |||
| 0b01be7b29 | |||
| ceebd3518b | |||
| a9249c6335 | |||
| dc22e6f158 | |||
| 1c7a34b367 | |||
| 526ae77b08 | |||
| 82698fb4b0 | |||
| 63ead04054 | |||
| 5727461522 | |||
| cd4292dd55 | |||
| 11ee8627b8 | |||
| 65ad79d727 | |||
| 85920ea8b1 | |||
| f4d2287e57 | |||
| 8a77a477df | |||
| 5a497e2dac | |||
| 7d5042012b | |||
| d2625d8607 | |||
| c3ec6b73e5 | |||
| 0ffe40c621 | |||
| 537f9111ae | |||
| d168d85650 | |||
| dbbc47a334 | |||
| 47760c37fc | |||
| 9fc785199a | |||
| f4f70634a1 | |||
| 046df6da76 | |||
| facca7b891 | |||
| a254e81ba9 | |||
| 09eb201b76 | |||
| b0226b54bd | |||
| 1d948c839d | |||
| 5d74b7252d | |||
| e787805b81 | |||
| 166d91ac48 | |||
| 2bb2124356 | |||
| 29ae1b7231 | |||
| 06dc67da49 | |||
| 42fe803a39 | |||
| 1dcaedab30 |
@@ -1,5 +1,4 @@
|
|||||||
.cvsignore
|
.cvsignore
|
||||||
.mfxcvsup
|
|
||||||
ChangeLog.cvs*
|
ChangeLog.cvs*
|
||||||
build
|
build
|
||||||
maint
|
maint
|
||||||
|
|||||||
@@ -8,9 +8,8 @@
|
|||||||
|
|
||||||
|
|
||||||
The Ultimate Packer for eXecutables
|
The Ultimate Packer for eXecutables
|
||||||
Copyright (c) 1996-2000 Markus Oberhumer & Laszlo Molnar
|
Copyright (c) 1996-2002 Markus Oberhumer & Laszlo Molnar
|
||||||
http://wildsau.idv.uni-linz.ac.at/mfx/upx.html
|
http://upx.sourceforge.net
|
||||||
http://upx.tsx.org
|
|
||||||
|
|
||||||
|
|
||||||
Limitations and other things which are not (yet) supported:
|
Limitations and other things which are not (yet) supported:
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
# Toplevel Makefile for UPX
|
# Toplevel Makefile for UPX
|
||||||
|
|
||||||
all:
|
SHELL = /bin/sh
|
||||||
$(MAKE) -C src/stub
|
|
||||||
$(MAKE) -C src
|
|
||||||
$(MAKE) -C doc
|
|
||||||
|
|
||||||
mostlyclean clean distclean maintainer-clean:
|
srcdir = .
|
||||||
|
top_srcdir = .
|
||||||
|
|
||||||
|
|
||||||
|
all mostlyclean clean distclean maintainer-clean:
|
||||||
|
$(MAKE) -C src/stub/util/sstrip $@
|
||||||
$(MAKE) -C src/stub $@
|
$(MAKE) -C src/stub $@
|
||||||
$(MAKE) -C src $@
|
$(MAKE) -C src $@
|
||||||
$(MAKE) -C doc $@
|
$(MAKE) -C doc $@
|
||||||
@@ -13,12 +15,16 @@ mostlyclean clean distclean maintainer-clean:
|
|||||||
dist: distclean
|
dist: distclean
|
||||||
false
|
false
|
||||||
|
|
||||||
|
zip:
|
||||||
|
cd .. && rm -f upx-current.zip && zip -r upx-current.zip upx
|
||||||
|
|
||||||
cvs-admin-ko:
|
cvs-admin-ko:
|
||||||
cvs admin -ko .
|
cvs admin -ko .
|
||||||
cvs update
|
cvs update
|
||||||
|
|
||||||
ChangeLog:
|
ChangeLog:
|
||||||
perl scripts/cvs2cl.pl --utc -f ChangeLog.cvs
|
perl $(srcdir)/scripts/cvs2cl.pl --utc -f ChangeLog.cvs
|
||||||
|
|
||||||
|
|
||||||
.PHONY: all mostlyclean clean distclean maintainer-clean
|
.PHONY: all mostlyclean clean distclean maintainer-clean
|
||||||
.PHONY: dist cvs-admin-ko ChangeLog
|
.PHONY: dist cvs-admin-ko ChangeLog
|
||||||
|
|||||||
@@ -2,14 +2,89 @@
|
|||||||
User visible changes for UPX
|
User visible changes for UPX
|
||||||
==================================================================
|
==================================================================
|
||||||
|
|
||||||
|
[ BETA VERSION - please see README.1ST for some more info ]
|
||||||
|
|
||||||
|
Changes in 1.90 beta (11 Nov 2002):
|
||||||
|
* UNSTABLE BETA VERSION - DO NOT USE EXCEPT FOR TESTING
|
||||||
|
* implemented several new options for finer compression control:
|
||||||
|
`--all-methods', `--all-filters' and `--brute'
|
||||||
|
* ps1/exe: new format - UPX now supports PlayStation One programs
|
||||||
|
* linux/386: added the option `--force-execve'
|
||||||
|
* vmlinuz/386: better kernel detection and sanity checks
|
||||||
|
* documentation updates
|
||||||
|
|
||||||
Changes in 1.11 beta (20 Dec 2000):
|
Changes in 1.11 beta (20 Dec 2000):
|
||||||
* UNSTABLE BETA VERSION - DO NOT USE EXCEPT FOR TESTING!!! REALLY.
|
* UNSTABLE BETA VERSION - DO NOT USE EXCEPT FOR TESTING
|
||||||
* vmlinuz/386: new format - UPX now supports bootable linux kernels
|
* vmlinuz/386: new format - UPX now supports bootable linux kernels
|
||||||
* linux/386: added the new direct-to-memory executable formats - no
|
* linux/elf386: added the new ELF direct-to-memory executable format - no
|
||||||
|
more temp files are needed for decompression!
|
||||||
|
* linux/sh386: added the new shell direct-to-memory executable format - no
|
||||||
more temp files are needed for decompression!
|
more temp files are needed for decompression!
|
||||||
* reduced overall memory requirements during packing
|
* reduced overall memory requirements during packing
|
||||||
* quite a number of internal source code rearrangements
|
* quite a number of internal source code rearrangements
|
||||||
|
|
||||||
|
==================================================================
|
||||||
|
|
||||||
|
Changes in 1.24 (07 Nov 2002)
|
||||||
|
* djgpp2/coff: stricter check of the COFF header to work around a
|
||||||
|
problem with certain binutils versions
|
||||||
|
|
||||||
|
Changes in 1.23 (05 Sep 2002)
|
||||||
|
* atari/tos: fixed an unpacking problem where a buffer was too
|
||||||
|
small (introduced in 1.22)
|
||||||
|
* linux/386: don't give up too early if a single block turns out
|
||||||
|
to be incompressible
|
||||||
|
* documentation: added some quick tips how to achieve the best
|
||||||
|
compression ratio for the final release of your application
|
||||||
|
* fixed a rare situation where the exit code was not set correctly
|
||||||
|
|
||||||
|
Changes in 1.22 (27 Jun 2002)
|
||||||
|
* atari/tos: the stub now flushes the CPU cache to avoid
|
||||||
|
problems on 68030+ machines
|
||||||
|
* source code: additional compiler support for Borland C++ 5.5.1,
|
||||||
|
Digital Mars C++ 8.28 and Watcom C++ 11.0c
|
||||||
|
|
||||||
|
Changes in 1.21 (01 Jun 2002)
|
||||||
|
* New option `--crp-ms=' for slightly better compression at the cost
|
||||||
|
of higher memory requirements during compression.
|
||||||
|
Try `upx --best --crp-ms=100000'. See the docs for more info.
|
||||||
|
* source code: portability fixes
|
||||||
|
* source code: compile fixes for g++ 3.0 and g++ 3.1
|
||||||
|
|
||||||
|
Changes in 1.20 (23 May 2001)
|
||||||
|
* slightly faster compression
|
||||||
|
* work around a gcc problem in the latest djgpp2 distribution
|
||||||
|
* watcom/le: fixed detection of already compressed files
|
||||||
|
* win32/pe: do not compress RT_MANIFEST resource types
|
||||||
|
* win32/pe: improved the error message for empty resource sections
|
||||||
|
* [NOTE: the jump from 1.08 to 1.20 is to avoid confusion with
|
||||||
|
our unstable development releases 1.1x and 1.9x]
|
||||||
|
|
||||||
|
Changes in 1.08 (30 Apr 2001)
|
||||||
|
* INFO: http://upx.sourceforge.net now is the new permanent UPX home page
|
||||||
|
* new native port to atari/tos
|
||||||
|
* win32/pe: shortened the identstring
|
||||||
|
* source code: portability fixes - UPX now builds cleanly under m68k CPUs
|
||||||
|
|
||||||
|
Changes in 1.07 (20 Feb 2001)
|
||||||
|
* win32/pe: corrected the TLS callback check
|
||||||
|
* win32/pe: really fixed that rare bug in relocation handling
|
||||||
|
* win32/pe: experimental support for SizeOfHeaders > 0x1000
|
||||||
|
* win32/pe: check for superfluous data between sections
|
||||||
|
* win32/pe: compressing screensavers (.scr) should finally work
|
||||||
|
|
||||||
|
Changes in 1.06 (27 Jan 2001)
|
||||||
|
* win32/pe: the check for TLS callbacks introduced in 1.05
|
||||||
|
was too strict - disabled for now
|
||||||
|
* dos/com: decreased the decompressor stack size a little bit
|
||||||
|
|
||||||
|
Changes in 1.05 (24 Jan 2001)
|
||||||
|
* win32/pe: refuse to compress programs with TLS callbacks
|
||||||
|
* win32/pe: stub changes to avoid slowdowns with some virus monitors
|
||||||
|
* win32/pe: reverted the relocation handling changes in 1.04
|
||||||
|
* linux/386: dont try to compress Linux kernel images (have a look
|
||||||
|
at the unstable UPX 1.1x beta versions for that)
|
||||||
|
|
||||||
Changes in 1.04 (19 Dec 2000)
|
Changes in 1.04 (19 Dec 2000)
|
||||||
* dos/exe: fixed an internal error when using `--no-reloc'
|
* dos/exe: fixed an internal error when using `--no-reloc'
|
||||||
* win32/pe: fixed a rare bug in the relocation handling code
|
* win32/pe: fixed a rare bug in the relocation handling code
|
||||||
@@ -188,7 +263,7 @@ Changes in 0.60 (06 Mar 1999)
|
|||||||
* fixed a bug which could make UPX hang when an exe header contained
|
* fixed a bug which could make UPX hang when an exe header contained
|
||||||
an illegal value
|
an illegal value
|
||||||
* added some compression flags for the win32/pe format
|
* added some compression flags for the win32/pe format
|
||||||
* added support for Atari ST executables (atari/tos)
|
* added support for Atari ST/TT executables (atari/tos)
|
||||||
* improved compression ratio
|
* improved compression ratio
|
||||||
* improved compression speed
|
* improved compression speed
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,8 @@
|
|||||||
|
|
||||||
|
|
||||||
The Ultimate Packer for eXecutables
|
The Ultimate Packer for eXecutables
|
||||||
Copyright (c) 1996-2000 Markus Oberhumer & Laszlo Molnar
|
Copyright (c) 1996-2002 Markus Oberhumer & Laszlo Molnar
|
||||||
http://wildsau.idv.uni-linz.ac.at/mfx/upx.html
|
http://upx.sourceforge.net
|
||||||
http://upx.tsx.org
|
|
||||||
|
|
||||||
|
|
||||||
Here are some possible projects from which you can choose if you'd like to
|
Here are some possible projects from which you can choose if you'd like to
|
||||||
@@ -31,8 +30,19 @@ User interface:
|
|||||||
More formats:
|
More formats:
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
- add more file formats / platforms (there were volunteers for FreeBSD,
|
- Amiga
|
||||||
BeOS, Windows CE, Amiga, C64, ...)
|
|
||||||
|
- BeOS
|
||||||
|
|
||||||
|
- C64
|
||||||
|
|
||||||
|
- elks/8086 (this is a 16-bit linux-8086 kernel)
|
||||||
|
See http://www.elks.ecs.soton.ac.uk/
|
||||||
|
|
||||||
|
- freebsd/386 (generic), freebsd/elf386 (specialized).
|
||||||
|
Probably could share most of the linux code.
|
||||||
|
|
||||||
|
- Windows CE
|
||||||
|
|
||||||
- add support for self-extracting HTML pages using a Javascript stub
|
- add support for self-extracting HTML pages using a Javascript stub
|
||||||
(like the AlgART HTML Packer "AHP")
|
(like the AlgART HTML Packer "AHP")
|
||||||
@@ -41,23 +51,20 @@ More formats:
|
|||||||
Existing formats:
|
Existing formats:
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
- dos/com: add support for very long files - convert to exe if necessary
|
- djgpp2/coff: add support for DLX dynamic loading
|
||||||
|
(see SEAL http://www.home.sk/public/seal/ )
|
||||||
|
|
||||||
- dos/sys: add support for sys/exe combos
|
- dos/com: add support for very long files - convert to exe if necessary
|
||||||
|
|
||||||
- dos/exe: implement filter support
|
- dos/exe: implement filter support
|
||||||
|
|
||||||
- djgpp2/coff: add support for DLX dynamic loading
|
- dos/sys: add support for sys/exe combos
|
||||||
(see SEAL http://www.home.sk/public/seal/ )
|
|
||||||
|
|
||||||
- linux/i386:
|
- linux/i386:
|
||||||
- use the new assembly preprocessor stuff (ie. process the file
|
- use the new assembly preprocessor stuff (ie. process the file
|
||||||
headers internally)
|
headers internally)
|
||||||
- UPX uncompressor daemon
|
- UPX uncompressor daemon
|
||||||
- rewrite the stub in assembly (not sure if this is a good idea...)
|
- rewrite the stub in assembly (not sure if this is a good idea...)
|
||||||
- etc...
|
|
||||||
- linux/i386: add a special elf/i386 format that understands
|
|
||||||
ELF files and has filter support
|
|
||||||
|
|
||||||
- watcom/le: add support for per section compression, LX support, VXD
|
- watcom/le: add support for per section compression, LX support, VXD
|
||||||
|
|
||||||
@@ -65,8 +72,6 @@ Existing formats:
|
|||||||
of problems (like importing a DLL or function fails)
|
of problems (like importing a DLL or function fails)
|
||||||
- win32/pe: finer control over resource compression, per section
|
- win32/pe: finer control over resource compression, per section
|
||||||
compression
|
compression
|
||||||
- win32/pe: compressing screensavers looses the description - probably
|
|
||||||
should not compress a special resource type
|
|
||||||
|
|
||||||
|
|
||||||
Compression ratio:
|
Compression ratio:
|
||||||
|
|||||||
@@ -8,23 +8,22 @@
|
|||||||
|
|
||||||
|
|
||||||
The Ultimate Packer for eXecutables
|
The Ultimate Packer for eXecutables
|
||||||
Copyright (c) 1996-2000 Markus Oberhumer & Laszlo Molnar
|
Copyright (c) 1996-2002 Markus Oberhumer & Laszlo Molnar
|
||||||
http://wildsau.idv.uni-linz.ac.at/mfx/upx.html
|
http://upx.sourceforge.net
|
||||||
http://upx.tsx.org
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
WARNING - UNSTABLE BETA VERSION
|
WARNING - UNSTABLE BETA VERSION
|
||||||
===============================
|
===============================
|
||||||
|
|
||||||
All versions 1.1x are unstable beta releases - use them only for testing,
|
All versions 1.9x are unstable beta releases - use them only for testing,
|
||||||
and never distribute a program that is packed with them !
|
and never distribute a program that is packed with them !
|
||||||
There will be hidden bugs. Really.
|
There will be hidden bugs. Really.
|
||||||
|
|
||||||
The current stable release is 1.04, and the next stable release
|
The current stable release is 1.22, and the next stable release
|
||||||
will be called version 1.20.
|
will be called version 2.00.
|
||||||
|
|
||||||
The main news since 1.04 are support for bootable Linux kernels ("vmlinuz/386")
|
The main news since 1.22 are support for bootable Linux kernels ("vmlinuz/386")
|
||||||
and direct Linux ELF-to-memory decompression ("linux/elf386"), so there's
|
and direct Linux ELF-to-memory decompression ("linux/elf386"), so there's
|
||||||
no reason to use the unstable versions unless you want to try the new formats.
|
no reason to use the unstable versions unless you want to try the new formats.
|
||||||
|
|
||||||
@@ -32,10 +31,9 @@ no reason to use the unstable versions unless you want to try the new formats.
|
|||||||
WELCOME
|
WELCOME
|
||||||
=======
|
=======
|
||||||
|
|
||||||
Welcome to UPX 1.0x, the first production release after almost two years
|
Welcome to UPX !
|
||||||
of beta testing.
|
|
||||||
|
|
||||||
Please don't forget to read the new LICENSE - UPX is now distributed
|
Please don't forget to read the file LICENSE - UPX is distributed
|
||||||
under the GNU General Public License (GPL) with special exceptions
|
under the GNU General Public License (GPL) with special exceptions
|
||||||
allowing the distribution of all compressed executables, including
|
allowing the distribution of all compressed executables, including
|
||||||
commercial programs.
|
commercial programs.
|
||||||
@@ -54,8 +52,8 @@ and run exactly as before, with no runtime or memory penalty for most
|
|||||||
of the supported formats.
|
of the supported formats.
|
||||||
|
|
||||||
UPX supports a number of different executable formats, including
|
UPX supports a number of different executable formats, including
|
||||||
Win95/98/ME/NT/2000 programs and DLLs, DOS programs, and Linux
|
Windows 95/98/ME/NT/2000/XP programs and DLLs, DOS programs,
|
||||||
executables and kernels.
|
and Linux executables and kernels.
|
||||||
|
|
||||||
UPX is free software distributed under the term of the GNU General
|
UPX is free software distributed under the term of the GNU General
|
||||||
Public License. Full source code is available.
|
Public License. Full source code is available.
|
||||||
@@ -64,7 +62,7 @@ UPX may be distributed and used freely, even with commercial applications.
|
|||||||
See the UPX License Agreement for details.
|
See the UPX License Agreement for details.
|
||||||
|
|
||||||
UPX is rated number one in the well known Archive Comparison Test. Visit
|
UPX is rated number one in the well known Archive Comparison Test. Visit
|
||||||
http://web.act.by.net/~act/act-exepack.html
|
http://compression.ca/ .
|
||||||
|
|
||||||
UPX aims to be Commercial Quality Freeware.
|
UPX aims to be Commercial Quality Freeware.
|
||||||
|
|
||||||
@@ -87,7 +85,7 @@ UPX comes with ABSOLUTELY NO WARRANTY; for details see the file LICENSE.
|
|||||||
Having said that, we think that UPX is quite stable now. Indeed we
|
Having said that, we think that UPX is quite stable now. Indeed we
|
||||||
have compressed lots of files without any problems. Also, the
|
have compressed lots of files without any problems. Also, the
|
||||||
current version has undergone several months of beta testing -
|
current version has undergone several months of beta testing -
|
||||||
actually it's almost 2 years since our first public beta.
|
actually it's more than 4 years since our first public beta.
|
||||||
|
|
||||||
This is the first production quality release, and we plan that future
|
This is the first production quality release, and we plan that future
|
||||||
releases will be backward compatible with this version.
|
releases will be backward compatible with this version.
|
||||||
@@ -114,8 +112,7 @@ THE FUTURE
|
|||||||
This only gives people a false feeling of security because
|
This only gives people a false feeling of security because
|
||||||
by definition all protectors/compressors can be broken.
|
by definition all protectors/compressors can be broken.
|
||||||
And don't trust any advertisment of authors of other executable
|
And don't trust any advertisment of authors of other executable
|
||||||
compressors about this topic - just do a websearch on something
|
compressors about this topic - just do a websearch on "unpackers"...
|
||||||
like "procdump"...
|
|
||||||
|
|
||||||
- Fix all remaining bugs - keep your reports coming ;-)
|
- Fix all remaining bugs - keep your reports coming ;-)
|
||||||
|
|
||||||
@@ -126,8 +123,8 @@ THE FUTURE
|
|||||||
COPYRIGHT
|
COPYRIGHT
|
||||||
=========
|
=========
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
|
|
||||||
This program may be used freely, and you are welcome to
|
This program may be used freely, and you are welcome to
|
||||||
redistribute it under certain conditions.
|
redistribute it under certain conditions.
|
||||||
@@ -146,7 +143,7 @@ Markus & Laszlo
|
|||||||
|
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+10
-7
@@ -14,15 +14,18 @@
|
|||||||
WARNING - UNSTABLE BETA VERSION
|
WARNING - UNSTABLE BETA VERSION
|
||||||
===============================
|
===============================
|
||||||
|
|
||||||
All versions 1.1x are unstable beta releases - use them only for testing,
|
All versions 1.9x are unstable beta releases - use them only for testing,
|
||||||
and never distribute a program that is packed with them !
|
and never distribute a program that is packed with them !
|
||||||
There will be hidden bugs. Really.
|
There will be hidden bugs. Really.
|
||||||
|
|
||||||
The current stable release is 1.04, and the next stable release
|
The current stable release is 1.24, and the next stable release
|
||||||
will be called version 1.20.
|
will be called version 2.00.
|
||||||
|
|
||||||
The main news since 1.04 are support for bootable Linux kernels ("vmlinuz/386")
|
|
||||||
and direct Linux ELF-to-memory decompression ("linux/elf386"), so there's
|
|
||||||
no reason to use the unstable versions unless you want to try the new formats.
|
|
||||||
|
|
||||||
|
The main news since 1.24 are:
|
||||||
|
- slightly better compression using the new NRV2E algorithm
|
||||||
|
- new options for compression tuining (e.g. `--brute')
|
||||||
|
- support for bootable Linux kernels ("vmlinuz/386")
|
||||||
|
- direct Linux ELF-to-memory decompression ("linux/elf386")
|
||||||
|
- support for playstation exes ("ps1/exe")
|
||||||
|
- lots of new bugs ;-) take care
|
||||||
|
|
||||||
|
|||||||
+15
-15
@@ -60,17 +60,16 @@ Prerequisites
|
|||||||
-------------
|
-------------
|
||||||
|
|
||||||
- first of all you need to build the UCL compression library
|
- first of all you need to build the UCL compression library
|
||||||
http://wildsau.idv.uni-linz.ac.at/mfx/ucl.html
|
http://www.oberhumer.com/opensource/ucl/
|
||||||
|
|
||||||
|
|
||||||
Tools needed to build/modify the UPX sources
|
Tools needed to build/modify the UPX sources
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
|
||||||
- A modern C++ compiler like gcc 2.95.2 or Visual C++ 6
|
- A modern C++ compiler like gcc 2.95.3 or Visual C++ 6
|
||||||
(egcs 1.1.x may work, half-baked implementations like Borland C++ 5.5 won't)
|
|
||||||
|
|
||||||
- GNU make for Win32
|
- GNU make for Win32
|
||||||
http://wildsau.idv.uni-linz.ac.at/mfx/download/upx/tools/
|
http://upx.sourceforge.net/download/tools/
|
||||||
|
|
||||||
- GNU make for DOS
|
- GNU make for DOS
|
||||||
ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/
|
ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/
|
||||||
@@ -81,34 +80,35 @@ To compile the packer sources
|
|||||||
|
|
||||||
set the environment variable UCLDIR to point to your UCL installation, e.g.
|
set the environment variable UCLDIR to point to your UCL installation, e.g.
|
||||||
|
|
||||||
set UCLDIR=c:\src\ucl-0.92 (DOS / Windows)
|
set UCLDIR=c:\src\ucl-1.01 (DOS / Windows)
|
||||||
export UCLDIR=$HOME/local/src/ucl-0.92 (Unix)
|
export UCLDIR=$HOME/local/src/ucl-1.01 (Unix)
|
||||||
|
|
||||||
then type
|
then type
|
||||||
|
|
||||||
make target=linux # on linux
|
make target=linux # on linux
|
||||||
make target=djgpp2 # for djgpp2
|
make target=djgpp2 # for djgpp2
|
||||||
make target=mingw32 # for mingw32
|
make target=mingw32 # for mingw32
|
||||||
|
make target=cygwin # cygwin 1.3.x
|
||||||
make target=no-cygwin # for mingw32 as included in cygwin
|
make target=no-cygwin # for mingw32 as included in cygwin
|
||||||
make target=msc # for Visual C++ 6.0
|
make target=vc6 # for Visual C++ 6.0
|
||||||
|
|
||||||
|
|
||||||
If you want to modify the stub sources you'll also need
|
If you want to modify the stub sources you'll also need
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
|
||||||
- Nasm - the Netwide Assembler
|
- Nasm 0.98.34 - the Netwide Assembler
|
||||||
http://www.cryogen.com/Nasm
|
http://upx.sourceforge.net/download/tools/
|
||||||
|
http://nasm.sourceforge.net/
|
||||||
- Perl 5.004 or better
|
|
||||||
ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/perl*b.zip
|
|
||||||
|
|
||||||
- A68K - a 68000 macro assembler
|
- A68K - a 68000 macro assembler
|
||||||
http://wildsau.idv.uni-linz.ac.at/mfx/download/upx/tools/
|
http://upx.sourceforge.net/download/tools/
|
||||||
|
|
||||||
- djasm - an assembler for the djgpp stub
|
- djasm - an assembler for the djgpp stub
|
||||||
http://wildsau.idv.uni-linz.ac.at/mfx/download/upx/tools/
|
http://upx.sourceforge.net/download/tools/
|
||||||
|
|
||||||
- Linux (for the linux/i386 stubs)
|
- Perl 5.004 or better
|
||||||
|
|
||||||
|
- Linux (for the linux/386 stubs)
|
||||||
|
|
||||||
|
|
||||||
Misc. notes
|
Misc. notes
|
||||||
|
|||||||
@@ -8,9 +8,8 @@
|
|||||||
|
|
||||||
|
|
||||||
The Ultimate Packer for eXecutables
|
The Ultimate Packer for eXecutables
|
||||||
Copyright (c) 1996-2000 Markus Oberhumer & Laszlo Molnar
|
Copyright (c) 1996-2002 Markus Oberhumer & Laszlo Molnar
|
||||||
http://wildsau.idv.uni-linz.ac.at/mfx/upx.html
|
http://upx.sourceforge.net
|
||||||
http://upx.tsx.org
|
|
||||||
|
|
||||||
|
|
||||||
.___.. .
|
.___.. .
|
||||||
|
|||||||
@@ -1,187 +1,111 @@
|
|||||||
NOTE: this TODO list is completely out of date (~ Dec 1999)
|
UPX TODO list. Last updated 2002-11-11.
|
||||||
|
|
||||||
===================================================================
|
- check all <const_cast> to make sure they are not invalid
|
||||||
|
|
||||||
- Rearrange this TODO list, sort by categories, add a priority (1-5)
|
- throwNotCompressible() is not a real error, so make the output nicer
|
||||||
|
(info: bla bla). Also ui.cpp (total_*).
|
||||||
|
|
||||||
|
|
||||||
For 0.95:
|
|
||||||
|
|
||||||
- FIXME: what do we want in 1.00 ???
|
IMPROVED COMPRESSION RATIO
|
||||||
|
==========================
|
||||||
|
|
||||||
- add NRV2D for dos/exe (use by default when >= 400 kB)
|
- experiment with new filters
|
||||||
|
|
||||||
- implement switch `-m' for method: 1 NRV2B, 2 NRV2D
|
- implement filters for dos/exe
|
||||||
|
|
||||||
- DLL problem under NT ? is this fixed ???
|
- filters: could we exploit a f->firstcall info field ?
|
||||||
|
|
||||||
|
- for small programs (e.g. < 64k), try an additional algorithm
|
||||||
|
to see if it gives better compression
|
||||||
|
|
||||||
|
|
||||||
PE
|
ALL FORMATS
|
||||||
==
|
===========
|
||||||
|
|
||||||
|
- more thoroughly test the exe-header in canPack()
|
||||||
|
and throw exceptions when encountering bad values.
|
||||||
|
|
||||||
|
- implement `--cpu=486' option to use bswap on the 32-bit formats
|
||||||
|
(if cpu >= 486)
|
||||||
|
|
||||||
|
- consider removing "or ebp,-1" when not needed
|
||||||
|
|
||||||
|
|
||||||
|
FORMAT DJGPP2/COFF
|
||||||
|
==================
|
||||||
|
|
||||||
|
- handle overlays
|
||||||
|
|
||||||
|
- fix default file extension handling when the --coff option is set
|
||||||
|
|
||||||
|
|
||||||
|
FORMAT DOS/EXE
|
||||||
|
==============
|
||||||
|
|
||||||
|
- implement filters
|
||||||
|
|
||||||
|
- add a check so that we don't pack djgpp1 binaries
|
||||||
|
|
||||||
|
|
||||||
|
FORMAT LINUX/386
|
||||||
|
================
|
||||||
|
|
||||||
|
- don't mmap() the temporary output file - this seems to improve
|
||||||
|
file io speed
|
||||||
|
|
||||||
|
|
||||||
|
FORMAT TMT/ADAM
|
||||||
|
===============
|
||||||
|
|
||||||
|
- the decompressors are already aligned, no need for an
|
||||||
|
extra alignment
|
||||||
|
|
||||||
|
|
||||||
|
FORMAT WATCOM/LE
|
||||||
|
================
|
||||||
|
|
||||||
|
- the decompressors are already aligned, no need for an
|
||||||
|
extra alignment
|
||||||
|
|
||||||
|
- fix default file extension handling when the --le option is set
|
||||||
|
|
||||||
|
- handle holes in the file
|
||||||
|
|
||||||
|
- implement compressWithFilters()
|
||||||
|
|
||||||
|
- add a call to verifyOverlappingDecompression()
|
||||||
|
|
||||||
|
|
||||||
|
FORMAT WIN16/NE
|
||||||
|
===============
|
||||||
|
|
||||||
|
- implement readFileHeader() to correctly identify a win16/ne
|
||||||
|
executable, so that the call for contribution will get thrown
|
||||||
|
|
||||||
|
|
||||||
|
FORMAT WIN32/PE
|
||||||
|
===============
|
||||||
|
|
||||||
|
- fix the section alignment with the Intel compiler
|
||||||
|
|
||||||
|
- decrease runtime memory overhead
|
||||||
|
|
||||||
2 - easy - mfx + ml) new switch(es) : do not compress resource types x,y,z
|
2 - easy - mfx + ml) new switch(es) : do not compress resource types x,y,z
|
||||||
or resource names a,b,c
|
or resource names a,b,c
|
||||||
|
|
||||||
3 - medium - ml) rebuild exports
|
3 - medium - ml) rebuild exports
|
||||||
|
|
||||||
3 - difficult) don't compress the BSS section and other holes.
|
3 - difficult) don't compress the BSS section and other holes.
|
||||||
|
|
||||||
4 - medium - ml) fix when objectalign < 0x1000
|
4 - medium - ml) fix when objectalign < 0x1000
|
||||||
|
|
||||||
4 - easy - ml) put the original offset of moved resources somewhere into
|
4 - easy - ml) put the original offset of moved resources somewhere into
|
||||||
the res.dir. (if it's safe to do)
|
the res.dir. (if it's safe to do)
|
||||||
|
|
||||||
4 - ??? - ml) fix FIXMEs
|
4 - ??? - ml) fix FIXMEs
|
||||||
|
|
||||||
5 - medium - ml) try to put the preprocessed imports & relocs back to their
|
5 - medium - ml) try to put the preprocessed imports & relocs back to their
|
||||||
original section if possible this could save some virtual memory
|
original section if possible. this could save some virtual memory
|
||||||
address space
|
address space.
|
||||||
|
|
||||||
|
|
||||||
COM
|
|
||||||
===
|
|
||||||
|
|
||||||
|
|
||||||
EXE
|
|
||||||
===
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
LE
|
|
||||||
==
|
|
||||||
|
|
||||||
4 - easy - ml) the decompressors are already aligned, no need for an
|
|
||||||
extra alignment
|
|
||||||
|
|
||||||
4 - difficult - ml) handle holes in the file
|
|
||||||
|
|
||||||
|
|
||||||
TMT
|
|
||||||
===
|
|
||||||
|
|
||||||
4 - easy - ml) the decompressors are already aligned, no need for an
|
|
||||||
extra alignment
|
|
||||||
|
|
||||||
|
|
||||||
LINUX
|
|
||||||
=====
|
|
||||||
|
|
||||||
4 - ???)
|
|
||||||
- test with AOUT binaries
|
|
||||||
- test with Java binaries
|
|
||||||
- make a compressed program suid. what happens ?
|
|
||||||
|
|
||||||
5 - difficult) rewrite the whole stub in assembly
|
|
||||||
|
|
||||||
|
|
||||||
SPARC
|
|
||||||
=====
|
|
||||||
|
|
||||||
3 - easy - ml) finish support - should generate byte-identical versions
|
|
||||||
for all formats (except those which are using Packer::getRandomId())
|
|
||||||
|
|
||||||
|
|
||||||
DJGPP2
|
|
||||||
======
|
|
||||||
|
|
||||||
1 - ???) do we support overlays at all ???
|
|
||||||
|
|
||||||
5 - ???) fix file extension handling when the --coff option is set
|
|
||||||
|
|
||||||
|
|
||||||
FOR 0.95
|
|
||||||
========
|
|
||||||
|
|
||||||
- enable automatic dependency tracking
|
|
||||||
|
|
||||||
1 - mfx) determine when to use NRV2D, find best c_flags values for
|
|
||||||
NRV2B & NRV2D (see util/runtest.sh)
|
|
||||||
|
|
||||||
5 - boring - mfx) Finally fix all screen and UI problems. How boring...
|
|
||||||
Probably should think about the whole system (printf vs. fprintf vs.
|
|
||||||
con_fprintf...)
|
|
||||||
|
|
||||||
5 - policy - ml+mfx) Discuss a default C++ style (GNU indent 2.2.3)
|
|
||||||
with Laszlo and use it. Or maybe Artistic Style?
|
|
||||||
|
|
||||||
10) Examine why pod2text breaks lines within something like `B<--coff>'.
|
|
||||||
(pod sucks anyway. unfortunately all alternatives as well.)
|
|
||||||
|
|
||||||
|
|
||||||
MISC
|
|
||||||
====
|
|
||||||
|
|
||||||
3 - difficult ml) The first two sentences of the README look too much like
|
|
||||||
those from the aspack docs. Laszlo, could you rewrite this ?
|
|
||||||
|
|
||||||
1 - easy - mfx) Check whether the compressed size of the executable is
|
|
||||||
really smaller than the uncompressed
|
|
||||||
|
|
||||||
1 - ??? - mfx) Implement a more informational interface.
|
|
||||||
Probably add some global functions in msg.cpp.
|
|
||||||
Should think about the requirements first, i.e. should there be
|
|
||||||
some simple hierarchies (header1, header2, ...) etc. ?
|
|
||||||
Could use the `-v' switch for enabling this (or `-i' ??).
|
|
||||||
- Something like this would be fine: (with colors :-)
|
|
||||||
[Processing kernel32.dll]
|
|
||||||
[Import]
|
|
||||||
3 DLL.
|
|
||||||
Original size: 12345 bytes.
|
|
||||||
Preprocessed size: 6789 bytes.
|
|
||||||
[Relocations]
|
|
||||||
Original size: 50000 bytes.
|
|
||||||
Preprocessed size: 25000 bytes.
|
|
||||||
[Exports]
|
|
||||||
<warning> exports compressed (try --compress-export=0 if needed)
|
|
||||||
[TLS]
|
|
||||||
Added 56 bytes TLS data.
|
|
||||||
Added 5 fixup records.
|
|
||||||
[Resources]
|
|
||||||
Directory size: 1234 bytes.
|
|
||||||
Resource data size: 100000 bytes.
|
|
||||||
Compressed resources: 8 (99900 bytes).
|
|
||||||
Not compressed resources: 1 (100 bytes).
|
|
||||||
|
|
||||||
3 - ???) delete temporary files when something wrong happens
|
|
||||||
|
|
||||||
4 - easy - ml) Add a `--486' option to use bswap on the 32-bit formats.
|
|
||||||
|
|
||||||
4 - easy - ml) consider removing 'sbb bp,bp' or "or ebp,-1" when not needed
|
|
||||||
|
|
||||||
5 - ???) idea: --subfile=xx compress xx. subfile: we'd need a list_subfiles
|
|
||||||
for this...
|
|
||||||
|
|
||||||
|
|
||||||
FIXME: classify
|
|
||||||
|
|
||||||
GOALS FOR 0.90
|
|
||||||
==============
|
|
||||||
|
|
||||||
- Provide additional NRV2D stubs for all 32-bit formats. Try to do this
|
|
||||||
in a generic way so that we can possibly add more algorithms.
|
|
||||||
Start by adding a `--nrv2d' switch.
|
|
||||||
|
|
||||||
FOR 0.90
|
|
||||||
========
|
|
||||||
|
|
||||||
/ update the output of `--help'
|
|
||||||
|
|
||||||
- filters: implement the missing scan() function for f_cto32.
|
|
||||||
Maybe could use this to try to find an optimal filter (e.g.
|
|
||||||
if level >= 9) based on the counts.
|
|
||||||
|
|
||||||
- filters: could we have use for a f->firstcall info field ?
|
|
||||||
|
|
||||||
TODO
|
|
||||||
====
|
|
||||||
|
|
||||||
- all formats: more thoroughly test the exe-header in canPack()
|
|
||||||
and throw exceptions when encountering bad values.
|
|
||||||
|
|
||||||
- experiment with filters
|
|
||||||
|
|
||||||
- for small programs (e.g. < 64k) try an additional algorithm (like
|
|
||||||
the non yet finished NRV2C) to see if it gives better compression ?
|
|
||||||
|
|
||||||
/ make checkerg++ work -> test
|
|
||||||
|
|
||||||
- fix file extension handling when the --coff option is set
|
|
||||||
|
|
||||||
- set up an "official" test suite
|
|
||||||
|
|
||||||
- finish documentation
|
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -3,14 +3,14 @@ SHELL = /bin/sh
|
|||||||
top_srcdir = ..
|
top_srcdir = ..
|
||||||
|
|
||||||
PACKAGE = upx
|
PACKAGE = upx
|
||||||
VERSION_DATE = 20 Dec 2000
|
VERSION_DATE = 11 Nov 2002
|
||||||
VERSION := $(shell sed -n 's/^.*UPX_VERSION_STRING .*"\(.*\)".*/\1/p' $(top_srcdir)/src/version.h)
|
VERSION := $(shell sed -n 's/^.*UPX_VERSION_STRING .*"\(.*\)".*/\1/p' $(top_srcdir)/src/version.h)
|
||||||
|
|
||||||
TRIMSPACE = cat
|
TRIMSPACE = cat
|
||||||
TRIMSPACE = sed -e 's/ *$$//'
|
TRIMSPACE = sed -e 's/ *$$//'
|
||||||
|
|
||||||
BUILT_SOURCES = upx.1 upx.doc upx.html upx.man upx.ps upx.tex
|
BUILT_SOURCES = upx.1 upx.doc upx.html upx.man upx.ps upx.tex
|
||||||
BUILT_SOURCES = upx.1 upx.doc upx.html upx.man
|
BUILT_SOURCES = upx.1 upx.doc upx.html
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
This documentation was written for those brave souls who want to
|
This documentation is written for those brave souls who want to
|
||||||
understand and/or modify the UPX assembly stubs - the small snippets
|
understand and/or modify the UPX assembly stubs - the small snippets
|
||||||
that do the runtime decompression when a compressed program is started.
|
that do the runtime decompression when a compressed program is started.
|
||||||
|
|
||||||
|
|||||||
+171
-62
@@ -13,10 +13,8 @@ B<upx> S<[ I<command> ]> S<[ I<options> ]> I<filename>...
|
|||||||
=head1 ABSTRACT
|
=head1 ABSTRACT
|
||||||
|
|
||||||
The Ultimate Packer for eXecutables
|
The Ultimate Packer for eXecutables
|
||||||
Copyright (c) 1996, 1997, 1998, 1999, 2000
|
Copyright (c) 1996-2002 Markus Oberhumer & Laszlo Molnar
|
||||||
Markus F.X.J. Oberhumer, Laszlo Molnar & John F. Reiser
|
http://upx.sourceforge.net
|
||||||
http://wildsau.idv.uni-linz.ac.at/mfx/upx.html
|
|
||||||
http://upx.tsx.org
|
|
||||||
|
|
||||||
|
|
||||||
B<UPX> is a portable, extendable, high-performance executable packer for
|
B<UPX> is a portable, extendable, high-performance executable packer for
|
||||||
@@ -24,24 +22,24 @@ several different executable formats. It achieves an excellent compression
|
|||||||
ratio and offers I<*very*> fast decompression. Your executables suffer
|
ratio and offers I<*very*> fast decompression. Your executables suffer
|
||||||
no memory overhead or other drawbacks for most of the formats supported.
|
no memory overhead or other drawbacks for most of the formats supported.
|
||||||
|
|
||||||
While you may use UPX freely for both non-commercial and commercial
|
While you may use B<UPX> freely for both non-commercial and commercial
|
||||||
executables (for details see the file LICENSE), we would highly
|
executables (for details see the file LICENSE), we would highly
|
||||||
appreciate if you credit UPX and ourselves in the documentation,
|
appreciate if you credit B<UPX> and ourselves in the documentation,
|
||||||
possibly including a reference to the UPX home page. Thanks.
|
possibly including a reference to the B<UPX> home page. Thanks.
|
||||||
|
|
||||||
[ Using UPX in non-OpenSource applications without proper credits
|
[ Using B<UPX> in non-OpenSource applications without proper credits
|
||||||
is considered not politically correct ;-) ]
|
is considered not politically correct ;-) ]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
=head1 DISCLAIMER
|
=head1 DISCLAIMER
|
||||||
|
|
||||||
UPX comes with ABSOLUTELY NO WARRANTY; for details see the file LICENSE.
|
B<UPX> comes with ABSOLUTELY NO WARRANTY; for details see the file LICENSE.
|
||||||
|
|
||||||
Having said that, we think that UPX is quite stable now. Indeed we
|
Having said that, we think that B<UPX> is quite stable now. Indeed we
|
||||||
have compressed lots of files without any problems. Also, the
|
have compressed lots of files without any problems. Also, the
|
||||||
current version has undergone several months of beta testing -
|
current version has undergone several months of beta testing -
|
||||||
actually it's more than 2 1/2 years since our first public beta.
|
actually it's more than 4 years since our first public beta back in 1998.
|
||||||
|
|
||||||
This is the first production quality release, and we plan that future 1.xx
|
This is the first production quality release, and we plan that future 1.xx
|
||||||
releases will be backward compatible with this version.
|
releases will be backward compatible with this version.
|
||||||
@@ -76,6 +74,7 @@ B<UPX> is a versatile executable packer with the following features:
|
|||||||
* linux/386
|
* linux/386
|
||||||
* linux/elf386
|
* linux/elf386
|
||||||
* linux/sh386
|
* linux/sh386
|
||||||
|
* ps1/exe
|
||||||
* rtm32/pe
|
* rtm32/pe
|
||||||
* tmt/adam
|
* tmt/adam
|
||||||
* vmlinuz/386 [bootable Linux kernel]
|
* vmlinuz/386 [bootable Linux kernel]
|
||||||
@@ -91,7 +90,7 @@ B<UPX> is a versatile executable packer with the following features:
|
|||||||
the full source code of UPX is released under the GNU General Public
|
the full source code of UPX is released under the GNU General Public
|
||||||
License (GPL) !
|
License (GPL) !
|
||||||
|
|
||||||
You probably understand now why we call UPX the "I<ultimate>"
|
You probably understand now why we call B<UPX> the "I<ultimate>"
|
||||||
executable packer.
|
executable packer.
|
||||||
|
|
||||||
|
|
||||||
@@ -105,7 +104,7 @@ specified on the command line.
|
|||||||
|
|
||||||
=head2 Decompress
|
=head2 Decompress
|
||||||
|
|
||||||
All UPX supported file formats can be unpacked using the B<-d> switch, eg.
|
All B<UPX> supported file formats can be unpacked using the B<-d> switch, eg.
|
||||||
B<upx -d yourfile.exe> will uncompress the file you've just compressed.
|
B<upx -d yourfile.exe> will uncompress the file you've just compressed.
|
||||||
|
|
||||||
=head2 Test
|
=head2 Test
|
||||||
@@ -135,9 +134,7 @@ B<-q -q -q> (or B<-qqq>): produce no output at all
|
|||||||
|
|
||||||
B<--help>: prints the help
|
B<--help>: prints the help
|
||||||
|
|
||||||
B<--version>: print the version of UPX
|
B<--version>: print the version of B<UPX>
|
||||||
|
|
||||||
B<--stdout>: writes all output to stdout
|
|
||||||
|
|
||||||
[ ...to be written... - type `B<upx --help>' for now ]
|
[ ...to be written... - type `B<upx --help>' for now ]
|
||||||
|
|
||||||
@@ -178,12 +175,23 @@ squeezes out even some more compression ratio. While it is usually fine
|
|||||||
to use this option with your favorite .com file it may take a long time
|
to use this option with your favorite .com file it may take a long time
|
||||||
to compress a multi-megabyte program. You have been warned.
|
to compress a multi-megabyte program. You have been warned.
|
||||||
|
|
||||||
Tips for even better compression:
|
Tips for achieving the best compression ratio:
|
||||||
|
|
||||||
=over 4
|
=over 4
|
||||||
|
|
||||||
=item *
|
=item *
|
||||||
|
|
||||||
|
Use the compression level B<--best>.
|
||||||
|
|
||||||
|
=item *
|
||||||
|
|
||||||
|
Try one or both of the options B<--all-methods> and B<--all-filters>.
|
||||||
|
|
||||||
|
Info: the option B<--brute> is an abbrevation for all the options
|
||||||
|
B<S<--best> S<--all-methods> S<--all-filters>>.
|
||||||
|
|
||||||
|
=item *
|
||||||
|
|
||||||
Try if B<--overlay=strip> works.
|
Try if B<--overlay=strip> works.
|
||||||
|
|
||||||
=item *
|
=item *
|
||||||
@@ -216,23 +224,19 @@ all executable formats.
|
|||||||
=head1 ENVIRONMENT
|
=head1 ENVIRONMENT
|
||||||
|
|
||||||
The environment variable B<UPX> can hold a set of default
|
The environment variable B<UPX> can hold a set of default
|
||||||
options for UPX. These options are interpreted first and
|
options for B<UPX>. These options are interpreted first and
|
||||||
can be overwritten by explicit command line parameters.
|
can be overwritten by explicit command line parameters.
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
for DOS/Windows: set UPX=-9 --compress-icons#1
|
for DOS/Windows: set UPX=-9 --compress-icons#0
|
||||||
for sh/ksh/zsh: UPX="-9 --compress-icons=1"; export UPX
|
for sh/ksh/zsh: UPX="-9 --compress-icons=0"; export UPX
|
||||||
for csh/tcsh: setenv UPX "-9 --compress-icons=1"
|
for csh/tcsh: setenv UPX "-9 --compress-icons=0"
|
||||||
|
|
||||||
Under DOS/Windows you must use '#' instead of '=' when setting the
|
Under DOS/Windows you must use '#' instead of '=' when setting the
|
||||||
environment variable because of a COMMAND.COM limitation.
|
environment variable because of a COMMAND.COM limitation.
|
||||||
|
|
||||||
On Vax/VMS, the name of the environment variable is
|
|
||||||
UPX_OPT, to avoid a conflict with the symbol set for
|
|
||||||
invocation of the program.
|
|
||||||
|
|
||||||
Not all of the options are valid in the environment variable -
|
Not all of the options are valid in the environment variable -
|
||||||
UPX will tell you.
|
B<UPX> will tell you.
|
||||||
|
|
||||||
You can use the B<--no-env> option to turn this support off.
|
You can use the B<--no-env> option to turn this support off.
|
||||||
|
|
||||||
@@ -242,8 +246,8 @@ You can use the B<--no-env> option to turn this support off.
|
|||||||
|
|
||||||
=head2 NOTES FOR ATARI/TOS
|
=head2 NOTES FOR ATARI/TOS
|
||||||
|
|
||||||
This is the executable format used by the Atari ST/TT, a 68000 based
|
This is the executable format used by the Atari ST/TT, a Motorola 68000
|
||||||
personal computer which was popular in the late '80s. Support
|
based personal computer which was popular in the late '80s. Support
|
||||||
of this format is only because of nostalgic feelings of one of
|
of this format is only because of nostalgic feelings of one of
|
||||||
the authors and serves no practical purpose :-).
|
the authors and serves no practical purpose :-).
|
||||||
|
|
||||||
@@ -252,7 +256,10 @@ All debug information will be stripped, though.
|
|||||||
|
|
||||||
Extra options available for this executable format:
|
Extra options available for this executable format:
|
||||||
|
|
||||||
(none)
|
--all-methods Compress the program several times, using all
|
||||||
|
available compression methods. This may improve
|
||||||
|
the compression ratio in some cases, but usually
|
||||||
|
the default method gives the best results anyway.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -264,7 +271,7 @@ Same as vmlinuz/i386.
|
|||||||
|
|
||||||
=head2 NOTES FOR DOS/COM
|
=head2 NOTES FOR DOS/COM
|
||||||
|
|
||||||
Obviously UPX won't work with executables that want to read data from
|
Obviously B<UPX> won't work with executables that want to read data from
|
||||||
themselves (like some commandline utilities that ship with Win95/98/ME).
|
themselves (like some commandline utilities that ship with Win95/98/ME).
|
||||||
|
|
||||||
Compressed programs only work on a 286+.
|
Compressed programs only work on a 286+.
|
||||||
@@ -277,13 +284,23 @@ Extra options available for this executable format:
|
|||||||
|
|
||||||
--8086 Create an executable that works on any 8086 CPU.
|
--8086 Create an executable that works on any 8086 CPU.
|
||||||
|
|
||||||
|
--all-methods Compress the program several times, using all
|
||||||
|
available compression methods. This may improve
|
||||||
|
the compression ratio in some cases, but usually
|
||||||
|
the default method gives the best results anyway.
|
||||||
|
|
||||||
|
--all-filters Compress the program several times, using all
|
||||||
|
available preprocessing filters. This may improve
|
||||||
|
the compression ratio in some cases, but usually
|
||||||
|
the default filter gives the best results anyway.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
=head2 NOTES FOR DOS/EXE
|
=head2 NOTES FOR DOS/EXE
|
||||||
|
|
||||||
dos/exe stands for all "normal" 16-bit DOS executables.
|
dos/exe stands for all "normal" 16-bit DOS executables.
|
||||||
|
|
||||||
Obviously UPX won't work with executables that want to read data from
|
Obviously B<UPX> won't work with executables that want to read data from
|
||||||
themselves (like some command line utilities that ship with Win95/98/ME).
|
themselves (like some command line utilities that ship with Win95/98/ME).
|
||||||
|
|
||||||
Compressed programs only work on a 286+.
|
Compressed programs only work on a 286+.
|
||||||
@@ -294,6 +311,11 @@ Extra options available for this executable format:
|
|||||||
|
|
||||||
--no-reloc Use no relocation records in the exe header.
|
--no-reloc Use no relocation records in the exe header.
|
||||||
|
|
||||||
|
--all-methods Compress the program several times, using all
|
||||||
|
available compression methods. This may improve
|
||||||
|
the compression ratio in some cases, but usually
|
||||||
|
the default method gives the best results anyway.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
=head2 NOTES FOR DOS/SYS
|
=head2 NOTES FOR DOS/SYS
|
||||||
@@ -311,33 +333,51 @@ Extra options available for this executable format:
|
|||||||
|
|
||||||
--8086 Create an executable that works on any 8086 CPU.
|
--8086 Create an executable that works on any 8086 CPU.
|
||||||
|
|
||||||
|
--all-methods Compress the program several times, using all
|
||||||
|
available compression methods. This may improve
|
||||||
|
the compression ratio in some cases, but usually
|
||||||
|
the default method gives the best results anyway.
|
||||||
|
|
||||||
|
--all-filters Compress the program several times, using all
|
||||||
|
available preprocessing filters. This may improve
|
||||||
|
the compression ratio in some cases, but usually
|
||||||
|
the default filter gives the best results anyway.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
=head2 NOTES FOR DJGPP2/COFF
|
=head2 NOTES FOR DJGPP2/COFF
|
||||||
|
|
||||||
First of all, it is recommended to use UPX *instead* of B<strip>. strip has
|
First of all, it is recommended to use B<UPX> *instead* of B<strip>. strip has
|
||||||
the very bad habit of replacing your stub with its own (outdated) version.
|
the very bad habit of replacing your stub with its own (outdated) version.
|
||||||
Additionally UPX corrects a bug/feature in strip v2.8.x: it
|
Additionally B<UPX> corrects a bug/feature in strip v2.8.x: it
|
||||||
will fix the 4 KByte aligment of the stub.
|
will fix the 4 KByte aligment of the stub.
|
||||||
|
|
||||||
UPX includes the full functionality of stubify. This means it will
|
B<UPX> includes the full functionality of stubify. This means it will
|
||||||
automatically stubify your COFF files. Use the option B<--coff> to
|
automatically stubify your COFF files. Use the option B<--coff> to
|
||||||
disable this behaviour (see below).
|
disable this behaviour (see below).
|
||||||
|
|
||||||
UPX automatically handles Allegro packfiles.
|
B<UPX> automatically handles Allegro packfiles.
|
||||||
|
|
||||||
The DLM format (a rather exotic shared library extension) is not supported.
|
The DLM format (a rather exotic shared library extension) is not supported.
|
||||||
|
|
||||||
Packed programs will be byte-identical to the original after uncompression.
|
Packed programs will be byte-identical to the original after uncompression.
|
||||||
All debug information and trailing garbage will be stripped, though.
|
All debug information and trailing garbage will be stripped, though.
|
||||||
|
|
||||||
BTW, UPX is the successor of the DJP executable packer.
|
|
||||||
|
|
||||||
Extra options available for this executable format:
|
Extra options available for this executable format:
|
||||||
|
|
||||||
--coff Produce COFF output instead of EXE. By default
|
--coff Produce COFF output instead of EXE. By default
|
||||||
UPX keeps your current stub.
|
UPX keeps your current stub.
|
||||||
|
|
||||||
|
--all-methods Compress the program several times, using all
|
||||||
|
available compression methods. This may improve
|
||||||
|
the compression ratio in some cases, but usually
|
||||||
|
the default method gives the best results anyway.
|
||||||
|
|
||||||
|
--all-filters Compress the program several times, using all
|
||||||
|
available preprocessing filters. This may improve
|
||||||
|
the compression ratio in some cases, but usually
|
||||||
|
the default filter gives the best results anyway.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
=head2 NOTES FOR LINUX [general]
|
=head2 NOTES FOR LINUX [general]
|
||||||
@@ -520,7 +560,7 @@ Extra options available for this executable format:
|
|||||||
Please read the general Linux description first.
|
Please read the general Linux description first.
|
||||||
|
|
||||||
Shell scripts where the underling shell accepts a ``-c'' argument
|
Shell scripts where the underling shell accepts a ``-c'' argument
|
||||||
can use the Linux/sh386 format. UPX decompresses the shell script
|
can use the Linux/sh386 format. B<UPX> decompresses the shell script
|
||||||
into low memory, then maps the shell and passes the entire text of the
|
into low memory, then maps the shell and passes the entire text of the
|
||||||
script as an argument with a leading ``-c''.
|
script as an argument with a leading ``-c''.
|
||||||
It does not use space in /tmp, and does not use /proc.
|
It does not use space in /tmp, and does not use /proc.
|
||||||
@@ -566,8 +606,9 @@ Extra options available for this executable format:
|
|||||||
|
|
||||||
Please read the general Linux description first.
|
Please read the general Linux description first.
|
||||||
|
|
||||||
The generic linux/386 format deompresses to /tmp
|
The generic linux/386 format decompresses to /tmp and needs
|
||||||
and needs /proc filesystem support.
|
/proc filesystem support. It starts the decompressed program
|
||||||
|
via the execve() syscall.
|
||||||
|
|
||||||
Linux/386 is only selected if the specialized linux/elf386
|
Linux/386 is only selected if the specialized linux/elf386
|
||||||
and linux/sh386 won't recognize a file.
|
and linux/sh386 won't recognize a file.
|
||||||
@@ -577,7 +618,7 @@ Packed programs will be byte-identical to the original after uncompression.
|
|||||||
How it works:
|
How it works:
|
||||||
|
|
||||||
For files which are not ELF and not a script for a known "-c" shell,
|
For files which are not ELF and not a script for a known "-c" shell,
|
||||||
UPX uses kernel exec(), which first requires decompressing to a
|
UPX uses kernel execve(), which first requires decompressing to a
|
||||||
temporary file in the filesystem. Interestingly -
|
temporary file in the filesystem. Interestingly -
|
||||||
because of the good memory management of the Linux kernel - this
|
because of the good memory management of the Linux kernel - this
|
||||||
often does not introduce a noticable delay, and in fact there
|
often does not introduce a noticable delay, and in fact there
|
||||||
@@ -625,7 +666,44 @@ Specific drawbacks:
|
|||||||
|
|
||||||
Extra options available for this executable format:
|
Extra options available for this executable format:
|
||||||
|
|
||||||
(none)
|
--force-execve Force the use of the generic linux/386 "execve"
|
||||||
|
format, i.e. do not try the linux/elf386 and
|
||||||
|
linux/sh386 formats.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=head2 NOTES FOR PS1/EXE
|
||||||
|
|
||||||
|
This is the executable format used by the Sony PlayStation (PSone),
|
||||||
|
a Mips R3000 based gaming console which is popular since the late '90s.
|
||||||
|
Support of this format is very similar to the Atari one, because of
|
||||||
|
nostalgic feelings of one of the authors, but this format maybe serves
|
||||||
|
a practical purpose ;-).
|
||||||
|
|
||||||
|
Packed programs will be byte-identical to the original after uncompression.
|
||||||
|
|
||||||
|
Maximum uncompressed size: ~1998848 bytes.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
- Normally the packed files use the same memory areas like the uncompressed
|
||||||
|
versions, so they will not override other memory areas while unpacking.
|
||||||
|
If this isn't possible UPX will abort showing a 'packed data overlap'
|
||||||
|
error. With the "--force" option UPX will set a few 'bytes higher' loading
|
||||||
|
offset for the packed file, but this isn't a real problem if it is a
|
||||||
|
single or boot-only executable.
|
||||||
|
|
||||||
|
Extra options available for this executable format:
|
||||||
|
|
||||||
|
--all-methods Compress the program several times, using all
|
||||||
|
available compression methods. This may improve
|
||||||
|
the compression ratio in some cases, but usually
|
||||||
|
the default method gives the best results anyway.
|
||||||
|
|
||||||
|
--no-align This option disables CD mode 2 data sector format
|
||||||
|
alignment. This will slightly increase the compression
|
||||||
|
ratio, but the compressed executable will not work
|
||||||
|
when started from a CD.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -641,15 +719,23 @@ This format is used by the TMT Pascal compiler - see http://www.tmt.com/ .
|
|||||||
|
|
||||||
Extra options available for this executable format:
|
Extra options available for this executable format:
|
||||||
|
|
||||||
(none)
|
--all-methods Compress the program several times, using all
|
||||||
|
available compression methods. This may improve
|
||||||
|
the compression ratio in some cases, but usually
|
||||||
|
the default method gives the best results anyway.
|
||||||
|
|
||||||
|
--all-filters Compress the program several times, using all
|
||||||
|
available preprocessing filters. This may improve
|
||||||
|
the compression ratio in some cases, but usually
|
||||||
|
the default filter gives the best results anyway.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
=head2 NOTES FOR VMLINUZ/386
|
=head2 NOTES FOR VMLINUZ/386
|
||||||
|
|
||||||
The vmlinuz/386 and bvmlinuz/386 formats take a gzip-compressed
|
The vmlinuz/386 and bvmlinuz/386 formats take a gzip-compressed
|
||||||
bootable kernel image ("vmlinuz", "zImage", "bzImage"), gzip-decompress
|
bootable Linux kernel image ("vmlinuz", "zImage", "bzImage"),
|
||||||
it and re-compress it with the UPX compression method.
|
gzip-decompress it and re-compress it with the B<UPX> compression method.
|
||||||
|
|
||||||
vmlinuz/386 is completely unrelated to the other Linux executable
|
vmlinuz/386 is completely unrelated to the other Linux executable
|
||||||
formats, and it does not share any of their drawbacks.
|
formats, and it does not share any of their drawbacks.
|
||||||
@@ -672,7 +758,8 @@ Benefits:
|
|||||||
641073 bzImage [original]
|
641073 bzImage [original]
|
||||||
560755 bzImage.upx [compressed by "upx -9"]
|
560755 bzImage.upx [compressed by "upx -9"]
|
||||||
|
|
||||||
- Much faster decompression at kernel boot time.
|
- Much faster decompression at kernel boot time (but decompression
|
||||||
|
speed is not really an issue these days).
|
||||||
|
|
||||||
Drawbacks:
|
Drawbacks:
|
||||||
|
|
||||||
@@ -680,22 +767,26 @@ Drawbacks:
|
|||||||
|
|
||||||
Extra options available for this executable format:
|
Extra options available for this executable format:
|
||||||
|
|
||||||
(none)
|
--all-methods Compress the program several times, using all
|
||||||
|
available compression methods. This may improve
|
||||||
|
the compression ratio in some cases, but usually
|
||||||
|
the default method gives the best results anyway.
|
||||||
|
|
||||||
|
--all-filters Compress the program several times, using all
|
||||||
|
available preprocessing filters. This may improve
|
||||||
|
the compression ratio in some cases, but usually
|
||||||
|
the default filter gives the best results anyway.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
=head2 NOTES FOR WATCOM/LE
|
=head2 NOTES FOR WATCOM/LE
|
||||||
|
|
||||||
UPX has been successfully tested with the following extenders:
|
B<UPX> has been successfully tested with the following extenders:
|
||||||
DOS4G, DOS4GW, PMODE/W, DOS32a, CauseWay.
|
DOS4G, DOS4GW, PMODE/W, DOS32a, CauseWay.
|
||||||
The WDOS/X extender is partly supported (for details
|
The WDOS/X extender is partly supported (for details
|
||||||
see the file bugs BUGS).
|
see the file bugs BUGS).
|
||||||
|
|
||||||
Yes, you can use your compressed executables with DOS4GW.
|
DLLs and the LX format are not supported.
|
||||||
|
|
||||||
The LX format is not yet supported.
|
|
||||||
|
|
||||||
DLLs are not supported.
|
|
||||||
|
|
||||||
Extra options available for this executable format:
|
Extra options available for this executable format:
|
||||||
|
|
||||||
@@ -706,10 +797,10 @@ Extra options available for this executable format:
|
|||||||
|
|
||||||
=head2 NOTES FOR WIN32/PE
|
=head2 NOTES FOR WIN32/PE
|
||||||
|
|
||||||
The PE support in UPX is quite stable now, but probably there are
|
The PE support in B<UPX> is quite stable now, but probably there are
|
||||||
still some incompabilities with some files.
|
still some incompabilities with some files.
|
||||||
|
|
||||||
Because of the way UPX (and other packers for this format) works, you
|
Because of the way B<UPX> (and other packers for this format) works, you
|
||||||
can see increased memory usage of your compressed files. If you start
|
can see increased memory usage of your compressed files. If you start
|
||||||
several instances of huge compressed programs you're wasting memory
|
several instances of huge compressed programs you're wasting memory
|
||||||
because the common segements of the program won't get shared
|
because the common segements of the program won't get shared
|
||||||
@@ -723,6 +814,10 @@ will load faster, and require less bandwidth during execution.
|
|||||||
|
|
||||||
DLLs are supported.
|
DLLs are supported.
|
||||||
|
|
||||||
|
Screensavers are supported, with the restriction that the filename
|
||||||
|
must end with ".scr" (as screensavers are handled slightly different
|
||||||
|
than normal exe files).
|
||||||
|
|
||||||
Extra options available for this executable format:
|
Extra options available for this executable format:
|
||||||
|
|
||||||
--compress-exports=0 Don't compress the export section.
|
--compress-exports=0 Don't compress the export section.
|
||||||
@@ -756,6 +851,16 @@ Extra options available for this executable format:
|
|||||||
UPX never strips relocations from a DLL
|
UPX never strips relocations from a DLL
|
||||||
regardless of this option.
|
regardless of this option.
|
||||||
|
|
||||||
|
--all-methods Compress the program several times, using all
|
||||||
|
available compression methods. This may improve
|
||||||
|
the compression ratio in some cases, but usually
|
||||||
|
the default method gives the best results anyway.
|
||||||
|
|
||||||
|
--all-filters Compress the program several times, using all
|
||||||
|
available preprocessing filters. This may improve
|
||||||
|
the compression ratio in some cases, but usually
|
||||||
|
the default filter gives the best results anyway.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
=head1 DIAGNOSTICS
|
=head1 DIAGNOSTICS
|
||||||
@@ -775,22 +880,26 @@ Please report all bugs immediately to the authors.
|
|||||||
|
|
||||||
=head1 AUTHORS
|
=head1 AUTHORS
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer <markus.oberhumer@jk.uni-linz.ac.at>
|
Markus F.X.J. Oberhumer <markus@oberhumer.com>
|
||||||
http://wildsau.idv.uni-linz.ac.at/mfx/
|
http://www.oberhumer.com
|
||||||
|
|
||||||
Laszlo Molnar <ml1050@cdata.tvnet.hu>
|
Laszlo Molnar <ml1050@users.sourceforge.net>
|
||||||
|
|
||||||
John F. Reiser <jreiser@BitWagon.com>
|
John F. Reiser <jreiser@BitWagon.com>
|
||||||
|
|
||||||
|
Jens Medoch <jssg@users.sourceforge.net>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
=head1 COPYRIGHT
|
=head1 COPYRIGHT
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
|
|
||||||
Copyright (C) 2000 John Reiser
|
Copyright (C) 2000-2002 John F. Reiser
|
||||||
|
|
||||||
|
Copyright (C) 2002 Jens Medoch
|
||||||
|
|
||||||
This program may be used freely, and you are welcome to
|
This program may be used freely, and you are welcome to
|
||||||
redistribute it under certain conditions.
|
redistribute it under certain conditions.
|
||||||
@@ -798,7 +907,7 @@ redistribute it under certain conditions.
|
|||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
UPX License Agreement for more details.
|
B<UPX License Agreement> for more details.
|
||||||
|
|
||||||
You should have received a copy of the UPX License Agreement along
|
You should have received a copy of the UPX License Agreement along
|
||||||
with this program; see the file LICENSE. If not, visit the UPX home page.
|
with this program; see the file LICENSE. If not, visit the UPX home page.
|
||||||
|
|||||||
+157
-39
@@ -8,8 +8,8 @@ exec perl -w -x $0 ${1+"$@"} # -*- mode: perl; perl-indent-level: 2; -*-
|
|||||||
### ###
|
### ###
|
||||||
##############################################################
|
##############################################################
|
||||||
|
|
||||||
## $Revision: 2.29 $
|
## $Revision: 2.38 $
|
||||||
## $Date: 2000/09/06 16:57:18 $
|
## $Date: 2001/02/12 19:54:35 $
|
||||||
## $Author: kfogel $
|
## $Author: kfogel $
|
||||||
##
|
##
|
||||||
## (C) 1999 Karl Fogel <kfogel@red-bean.com>, under the GNU GPL.
|
## (C) 1999 Karl Fogel <kfogel@red-bean.com>, under the GNU GPL.
|
||||||
@@ -78,7 +78,7 @@ use File::Basename;
|
|||||||
my $Log_Source_Command = "cvs log";
|
my $Log_Source_Command = "cvs log";
|
||||||
|
|
||||||
# In case we have to print it out:
|
# In case we have to print it out:
|
||||||
my $VERSION = '$Revision: 2.29 $';
|
my $VERSION = '$Revision: 2.38 $';
|
||||||
$VERSION =~ s/\S+\s+(\S+)\s+\S+/$1/;
|
$VERSION =~ s/\S+\s+(\S+)\s+\S+/$1/;
|
||||||
|
|
||||||
## Vars set by options:
|
## Vars set by options:
|
||||||
@@ -98,6 +98,10 @@ my $Distributed = 0;
|
|||||||
# What file should we generate (defaults to "ChangeLog")?
|
# What file should we generate (defaults to "ChangeLog")?
|
||||||
my $Log_File_Name = "ChangeLog";
|
my $Log_File_Name = "ChangeLog";
|
||||||
|
|
||||||
|
# Grab most recent entry date from existing ChangeLog file, just add
|
||||||
|
# to that ChangeLog.
|
||||||
|
my $Cumulative = 0;
|
||||||
|
|
||||||
# Expand usernames to email addresses based on a map file?
|
# Expand usernames to email addresses based on a map file?
|
||||||
my $User_Map_File = "";
|
my $User_Map_File = "";
|
||||||
|
|
||||||
@@ -196,6 +200,33 @@ my $logmsg_separator = "----------------------------";
|
|||||||
|
|
||||||
### Everything below is subroutine definitions. ###
|
### Everything below is subroutine definitions. ###
|
||||||
|
|
||||||
|
# If accumulating, grab the boundary date from pre-existing ChangeLog.
|
||||||
|
sub maybe_grab_accumulation_date ()
|
||||||
|
{
|
||||||
|
if (! $Cumulative) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
# else
|
||||||
|
|
||||||
|
open (LOG, "$Log_File_Name")
|
||||||
|
or die ("trouble opening $Log_File_Name for reading ($!)");
|
||||||
|
|
||||||
|
my $boundary_date;
|
||||||
|
while (<LOG>)
|
||||||
|
{
|
||||||
|
if (/^(\d\d\d\d-\d\d-\d\d\s+\d\d:\d\d)/)
|
||||||
|
{
|
||||||
|
$boundary_date = "$1";
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close (LOG);
|
||||||
|
return $boundary_date;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# Fills up a ChangeLog structure in the current directory.
|
# Fills up a ChangeLog structure in the current directory.
|
||||||
sub derive_change_log ()
|
sub derive_change_log ()
|
||||||
{
|
{
|
||||||
@@ -210,6 +241,12 @@ sub derive_change_log ()
|
|||||||
my $msg_txt;
|
my $msg_txt;
|
||||||
my $detected_file_separator;
|
my $detected_file_separator;
|
||||||
|
|
||||||
|
# Might be adding to an existing ChangeLog
|
||||||
|
my $accumulation_date = &maybe_grab_accumulation_date ();
|
||||||
|
if ($accumulation_date) {
|
||||||
|
$Log_Source_Command .= " -d\'>${accumulation_date}\'";
|
||||||
|
}
|
||||||
|
|
||||||
# We might be expanding usernames
|
# We might be expanding usernames
|
||||||
my %usermap;
|
my %usermap;
|
||||||
|
|
||||||
@@ -605,6 +642,7 @@ sub derive_change_log ()
|
|||||||
undef $file_full_path;
|
undef $file_full_path;
|
||||||
undef %branch_names;
|
undef %branch_names;
|
||||||
undef %branch_numbers;
|
undef %branch_numbers;
|
||||||
|
undef %symbolic_names;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -804,6 +842,41 @@ sub derive_change_log ()
|
|||||||
|
|
||||||
if (! $Output_To_Stdout)
|
if (! $Output_To_Stdout)
|
||||||
{
|
{
|
||||||
|
# If accumulating, append old data to new before renaming. But
|
||||||
|
# don't append the most recent entry, since it's already in the
|
||||||
|
# new log due to CVS's idiosyncratic interpretation of "log -d".
|
||||||
|
if ($Cumulative && -f $logfile_here)
|
||||||
|
{
|
||||||
|
open (NEW_LOG, ">>$tmpfile")
|
||||||
|
or die "trouble appending to $tmpfile ($!)";
|
||||||
|
|
||||||
|
open (OLD_LOG, "<$logfile_here")
|
||||||
|
or die "trouble reading from $logfile_here ($!)";
|
||||||
|
|
||||||
|
my $started_first_entry = 0;
|
||||||
|
my $passed_first_entry = 0;
|
||||||
|
while (<OLD_LOG>)
|
||||||
|
{
|
||||||
|
if (! $passed_first_entry)
|
||||||
|
{
|
||||||
|
if ((! $started_first_entry)
|
||||||
|
&& /^(\d\d\d\d-\d\d-\d\d\s+\d\d:\d\d)/) {
|
||||||
|
$started_first_entry = 1;
|
||||||
|
}
|
||||||
|
elsif (/^(\d\d\d\d-\d\d-\d\d\s+\d\d:\d\d)/) {
|
||||||
|
$passed_first_entry = 1;
|
||||||
|
print NEW_LOG $_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print NEW_LOG $_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close (NEW_LOG);
|
||||||
|
close (OLD_LOG);
|
||||||
|
}
|
||||||
|
|
||||||
if (-f $logfile_here) {
|
if (-f $logfile_here) {
|
||||||
rename ($logfile_here, $logfile_bak);
|
rename ($logfile_here, $logfile_bak);
|
||||||
}
|
}
|
||||||
@@ -1017,7 +1090,7 @@ sub pretty_file_list ()
|
|||||||
# Collect the revision numbers' last components, but don't
|
# Collect the revision numbers' last components, but don't
|
||||||
# print them -- they'll get printed with the branch name
|
# print them -- they'll get printed with the branch name
|
||||||
# later.
|
# later.
|
||||||
$$qunkref{'revision'} =~ /.+\.([\d])+$/;
|
$$qunkref{'revision'} =~ /.+\.([\d]+)$/;
|
||||||
push (@brevisions, $1);
|
push (@brevisions, $1);
|
||||||
|
|
||||||
# todo: we're still collecting branch roots, but we're not
|
# todo: we're still collecting branch roots, but we're not
|
||||||
@@ -1193,9 +1266,10 @@ sub wrap_log_entry ()
|
|||||||
my $max_line_length = shift; # Amount left for a blank line.
|
my $max_line_length = shift; # Amount left for a blank line.
|
||||||
|
|
||||||
my $wrapped_text = ""; # The accumulating wrapped entry.
|
my $wrapped_text = ""; # The accumulating wrapped entry.
|
||||||
my $indentation = ""; # Inherited indentation from prev line.
|
my $user_indent = ""; # Inherited user_indent from prev line.
|
||||||
|
|
||||||
my $first_time = 1; # Is this the first iteration of the loop?
|
my $first_time = 1; # First iteration of the loop?
|
||||||
|
my $suppress_line_start_match = 0; # Set to disable line start checks.
|
||||||
|
|
||||||
my @lines = split (/\n/, $text);
|
my @lines = split (/\n/, $text);
|
||||||
while (@lines) # Don't use `foreach' here, it won't work.
|
while (@lines) # Don't use `foreach' here, it won't work.
|
||||||
@@ -1203,13 +1277,24 @@ sub wrap_log_entry ()
|
|||||||
my $this_line = shift (@lines);
|
my $this_line = shift (@lines);
|
||||||
chomp $this_line;
|
chomp $this_line;
|
||||||
|
|
||||||
# First, if it matches any of the line-start regexps, then print a
|
if ($this_line =~ /^(\s+)/) {
|
||||||
# newline now...
|
$user_indent = $1;
|
||||||
if (($this_line =~ /^(\s*)\*\s+[a-zA-Z0-9]/)
|
}
|
||||||
|
else {
|
||||||
|
$user_indent = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
# If it matches any of the line-start regexps, print a newline now...
|
||||||
|
if ($suppress_line_start_match)
|
||||||
|
{
|
||||||
|
$suppress_line_start_match = 0;
|
||||||
|
}
|
||||||
|
elsif (($this_line =~ /^(\s*)\*\s+[a-zA-Z0-9]/)
|
||||||
|| ($this_line =~ /^(\s*)\* [a-zA-Z0-9_\.\/\+-]+/)
|
|| ($this_line =~ /^(\s*)\* [a-zA-Z0-9_\.\/\+-]+/)
|
||||||
|| ($this_line =~ /^(\s*)\([a-zA-Z0-9_\.\/\+-]+(\)|,\s*)/)
|
|| ($this_line =~ /^(\s*)\([a-zA-Z0-9_\.\/\+-]+(\)|,\s*)/)
|
||||||
|
|| ($this_line =~ /^(\s+)(\S+)/)
|
||||||
|| ($this_line =~ /^(\s*)- +/)
|
|| ($this_line =~ /^(\s*)- +/)
|
||||||
|| ($this_line =~ /^(\s*)[^\s]+:\s*$/)
|
|| ($this_line =~ /^()\s*$/)
|
||||||
|| ($this_line =~ /^(\s*)\*\) +/)
|
|| ($this_line =~ /^(\s*)\*\) +/)
|
||||||
|| ($this_line =~ /^(\s*)[a-zA-Z0-9](\)|\.|\:) +/))
|
|| ($this_line =~ /^(\s*)[a-zA-Z0-9](\)|\.|\:) +/))
|
||||||
{
|
{
|
||||||
@@ -1217,15 +1302,20 @@ sub wrap_log_entry ()
|
|||||||
# and this line is the first line in the entry, in which case
|
# and this line is the first line in the entry, in which case
|
||||||
# we're getting the blank line for free already and shouldn't
|
# we're getting the blank line for free already and shouldn't
|
||||||
# add an extra one.
|
# add an extra one.
|
||||||
unless (($After_Header ne " ") and ($first_time)) {
|
unless (($After_Header ne " ") and ($first_time))
|
||||||
|
{
|
||||||
|
if ($this_line =~ /^()\s*$/) {
|
||||||
|
$suppress_line_start_match = 1;
|
||||||
$wrapped_text .= "\n${left_pad_str}";
|
$wrapped_text .= "\n${left_pad_str}";
|
||||||
}
|
}
|
||||||
|
|
||||||
$indentation = $1;
|
$wrapped_text .= "\n${left_pad_str}";
|
||||||
$length_remaining = $max_line_length - (length ($indentation));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Now that any indentation has been preserved, strip off leading
|
$length_remaining = $max_line_length - (length ($user_indent));
|
||||||
|
}
|
||||||
|
|
||||||
|
# Now that any user_indent has been preserved, strip off leading
|
||||||
# whitespace, so up-folding has no ugly side-effects.
|
# whitespace, so up-folding has no ugly side-effects.
|
||||||
$this_line =~ s/^\s*//;
|
$this_line =~ s/^\s*//;
|
||||||
|
|
||||||
@@ -1233,13 +1323,11 @@ sub wrap_log_entry ()
|
|||||||
my $this_len = length ($this_line);
|
my $this_len = length ($this_line);
|
||||||
if ($this_len == 0)
|
if ($this_len == 0)
|
||||||
{
|
{
|
||||||
# Blank lines should be preserved, and should cancel any
|
# Blank lines should cancel any user_indent level.
|
||||||
# indentation level.
|
$user_indent = "";
|
||||||
$this_line = "\n${left_pad_str}";
|
|
||||||
$indentation = "";
|
|
||||||
$length_remaining = $max_line_length;
|
$length_remaining = $max_line_length;
|
||||||
}
|
}
|
||||||
elsif ($this_len >= $length_remaining)
|
elsif ($this_len >= $length_remaining) # Line too long, try breaking it.
|
||||||
{
|
{
|
||||||
# Walk backwards from the end. At first acceptable spot, break
|
# Walk backwards from the end. At first acceptable spot, break
|
||||||
# a new line.
|
# a new line.
|
||||||
@@ -1260,13 +1348,34 @@ sub wrap_log_entry ()
|
|||||||
$this_line .= "\n${left_pad_str}";
|
$this_line .= "\n${left_pad_str}";
|
||||||
|
|
||||||
# Make sure the next line is allowed full room.
|
# Make sure the next line is allowed full room.
|
||||||
$length_remaining = $max_line_length - (length ($indentation));
|
$length_remaining = $max_line_length - (length ($user_indent));
|
||||||
|
|
||||||
# Strip next_line, but then preserve any indentation.
|
# Strip next_line, but then preserve any user_indent.
|
||||||
$next_line =~ s/^\s*//;
|
$next_line =~ s/^\s*//;
|
||||||
$next_line = $indentation . $next_line;
|
|
||||||
|
|
||||||
|
# Sneak a peek at the user_indent of the upcoming line, so
|
||||||
|
# $next_line (which will now precede it) can inherit that
|
||||||
|
# indent level. Otherwise, use whatever user_indent level
|
||||||
|
# we currently have, which might be none.
|
||||||
|
my $next_next_line = shift (@lines);
|
||||||
|
if ((defined ($next_next_line)) && ($next_next_line =~ /^(\s+)/)) {
|
||||||
|
$next_line = $1 . $next_line if (defined ($1));
|
||||||
|
# $length_remaining = $max_line_length - (length ($1));
|
||||||
|
$next_next_line =~ s/^\s*//;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$next_line = $user_indent . $next_line;
|
||||||
|
}
|
||||||
|
if (defined ($next_next_line)) {
|
||||||
|
unshift (@lines, $next_next_line);
|
||||||
|
}
|
||||||
unshift (@lines, $next_line);
|
unshift (@lines, $next_line);
|
||||||
|
|
||||||
|
# Our new next line might, coincidentally, begin with one of
|
||||||
|
# the line-start regexps, so we temporarily turn off
|
||||||
|
# sensitivity to that until we're past the line.
|
||||||
|
$suppress_line_start_match = 1;
|
||||||
|
|
||||||
last;
|
last;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1275,11 +1384,14 @@ sub wrap_log_entry ()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# If we just bottomed out, the line is too long, so just break
|
|
||||||
# it where the original text does.
|
|
||||||
if ($idx == 0)
|
if ($idx == 0)
|
||||||
{
|
{
|
||||||
if ($length_remaining == ($max_line_length - (length ($indentation))))
|
# We bottomed out because the line is longer than the
|
||||||
|
# available space. But that could be because the space is
|
||||||
|
# small, or because the line is longer than even the maximum
|
||||||
|
# possible space. Handle both cases below.
|
||||||
|
|
||||||
|
if ($length_remaining == ($max_line_length - (length ($user_indent))))
|
||||||
{
|
{
|
||||||
# The line is simply too long -- there is no hope of ever
|
# The line is simply too long -- there is no hope of ever
|
||||||
# breaking it nicely, so just insert it verbatim, with
|
# breaking it nicely, so just insert it verbatim, with
|
||||||
@@ -1288,9 +1400,9 @@ sub wrap_log_entry ()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
# Can't break it here, but may be able to on the next round.
|
# Can't break it here, but may be able to on the next round...
|
||||||
unshift (@lines, $this_line);
|
unshift (@lines, $this_line);
|
||||||
$length_remaining = $max_line_length - (length ($indentation));
|
$length_remaining = $max_line_length - (length ($user_indent));
|
||||||
$this_line = "\n${left_pad_str}";
|
$this_line = "\n${left_pad_str}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1315,7 +1427,7 @@ sub wrap_log_entry ()
|
|||||||
# Unconditionally indicate that loop has run at least once.
|
# Unconditionally indicate that loop has run at least once.
|
||||||
$first_time = 0;
|
$first_time = 0;
|
||||||
|
|
||||||
$wrapped_text .= "${this_line}";
|
$wrapped_text .= "${user_indent}${this_line}";
|
||||||
}
|
}
|
||||||
|
|
||||||
# One last bit of padding.
|
# One last bit of padding.
|
||||||
@@ -1413,6 +1525,9 @@ sub parse_options ()
|
|||||||
my $narg = shift (@ARGV) || die "$arg needs argument.\n";
|
my $narg = shift (@ARGV) || die "$arg needs argument.\n";
|
||||||
$output_file = $narg;
|
$output_file = $narg;
|
||||||
}
|
}
|
||||||
|
elsif ($arg =~ /^--accum$/) {
|
||||||
|
$Cumulative = 1;
|
||||||
|
}
|
||||||
elsif ($arg =~ /^--fsf$/) {
|
elsif ($arg =~ /^--fsf$/) {
|
||||||
$FSF_Style = 1;
|
$FSF_Style = 1;
|
||||||
}
|
}
|
||||||
@@ -1507,6 +1622,11 @@ sub parse_options ()
|
|||||||
$exit_with_admonishment = 1;
|
$exit_with_admonishment = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($XML_Output && $Cumulative) {
|
||||||
|
print STDERR "cannot pass both --xml and --accum\n";
|
||||||
|
$exit_with_admonishment = 1;
|
||||||
|
}
|
||||||
|
|
||||||
# Or if any other error message has already been printed out, we
|
# Or if any other error message has already been printed out, we
|
||||||
# just leave now:
|
# just leave now:
|
||||||
if ($exit_with_admonishment) {
|
if ($exit_with_admonishment) {
|
||||||
@@ -1524,10 +1644,7 @@ sub parse_options ()
|
|||||||
|
|
||||||
## Else no problems, so proceed.
|
## Else no problems, so proceed.
|
||||||
|
|
||||||
if ($Output_To_Stdout) {
|
if ($output_file) {
|
||||||
undef $Log_File_Name; # not actually necessary
|
|
||||||
}
|
|
||||||
elsif ($output_file) {
|
|
||||||
$Log_File_Name = $output_file;
|
$Log_File_Name = $output_file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1627,6 +1744,7 @@ Options/Arguments:
|
|||||||
-S, --separate-header Blank line between each header and log message
|
-S, --separate-header Blank line between each header and log message
|
||||||
--no-wrap Don't auto-wrap log message (recommend -S also)
|
--no-wrap Don't auto-wrap log message (recommend -S also)
|
||||||
--gmt, --utc Show times in GMT/UTC instead of local time
|
--gmt, --utc Show times in GMT/UTC instead of local time
|
||||||
|
--accum Add to an existing ChangeLog (incompat w/ --xml)
|
||||||
-w, --day-of-week Show day of week
|
-w, --day-of-week Show day of week
|
||||||
--header FILE Get ChangeLog header from FILE ("-" means stdin)
|
--header FILE Get ChangeLog header from FILE ("-" means stdin)
|
||||||
--xml Output XML instead of ChangeLog format
|
--xml Output XML instead of ChangeLog format
|
||||||
@@ -1636,7 +1754,7 @@ Options/Arguments:
|
|||||||
-l OPTS, --log-opts OPTS Invoke like this "cvs ... log OPTS"
|
-l OPTS, --log-opts OPTS Invoke like this "cvs ... log OPTS"
|
||||||
FILE1 [FILE2 ...] Show only log information for the named FILE(s)
|
FILE1 [FILE2 ...] Show only log information for the named FILE(s)
|
||||||
|
|
||||||
See http://www.red-bean.com/~kfogel/cvs2cl.shtml for maintenance and bug info.
|
See http://www.red-bean.com/cvs2cl for maintenance and bug info.
|
||||||
END_OF_INFO
|
END_OF_INFO
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1655,11 +1773,11 @@ information. Basic usage: just run it inside a working copy and a
|
|||||||
ChangeLog will appear. It requires repository access (i.e., 'cvs log'
|
ChangeLog will appear. It requires repository access (i.e., 'cvs log'
|
||||||
must work). Run "cvs2cl.pl --help" to see more advanced options.
|
must work). Run "cvs2cl.pl --help" to see more advanced options.
|
||||||
|
|
||||||
See http://www.red-bean.com/~kfogel/cvs2cl.shtml for updates, and
|
See http://www.red-bean.com/cvs2cl for updates, and for instructions
|
||||||
for instructions on getting anonymous CVS access to this script.
|
on getting anonymous CVS access to this script.
|
||||||
|
|
||||||
Maintainer: Karl Fogel <kfogel@red-bean.com>
|
Maintainer: Karl Fogel <kfogel@red-bean.com>
|
||||||
Please report bugs to <cvs2cl-bugs@red-bean.com>.
|
Please report bugs to <bug-cvs2cl@red-bean.com>.
|
||||||
|
|
||||||
=head1 README
|
=head1 README
|
||||||
|
|
||||||
@@ -1668,11 +1786,11 @@ information. Basic usage: just run it inside a working copy and a
|
|||||||
ChangeLog will appear. It requires repository access (i.e., 'cvs log'
|
ChangeLog will appear. It requires repository access (i.e., 'cvs log'
|
||||||
must work). Run "cvs2cl.pl --help" to see more advanced options.
|
must work). Run "cvs2cl.pl --help" to see more advanced options.
|
||||||
|
|
||||||
See http://www.red-bean.com/~kfogel/cvs2cl.shtml for updates, and
|
See http://www.red-bean.com/cvs2cl for updates, and for instructions
|
||||||
for instructions on getting anonymous CVS access to this script.
|
on getting anonymous CVS access to this script.
|
||||||
|
|
||||||
Maintainer: Karl Fogel <kfogel@red-bean.com>
|
Maintainer: Karl Fogel <kfogel@red-bean.com>
|
||||||
Please report bugs to <cvs2cl-bugs@red-bean.com>.
|
Please report bugs to <bug-cvs2cl@red-bean.com>.
|
||||||
|
|
||||||
=head1 PREREQUISITES
|
=head1 PREREQUISITES
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,17 @@
|
|||||||
|
GNUmakefile
|
||||||
*.0??
|
*.0??
|
||||||
|
*.dat
|
||||||
*.idb
|
*.idb
|
||||||
|
*.img
|
||||||
*.map
|
*.map
|
||||||
|
*.raw
|
||||||
|
*.rel
|
||||||
*.pdb
|
*.pdb
|
||||||
*.upx
|
*.upx
|
||||||
.gdbinit
|
.gdbinit
|
||||||
.Attic
|
.Attic
|
||||||
|
.deps
|
||||||
|
compress_nrv.*
|
||||||
upx
|
upx
|
||||||
upx_nrv
|
upx_nrv
|
||||||
upx_nrv.*
|
upx_nrv.*
|
||||||
|
|||||||
+359
-216
@@ -1,12 +1,19 @@
|
|||||||
# UPX Makefile (GNU make) - works with djgpp2/win32/unix
|
#
|
||||||
|
# UPX Makefile (GNU make) - works with unix/win32/djgpp2
|
||||||
#
|
#
|
||||||
# usage:
|
# usage:
|
||||||
# `make target=linux' # linux
|
# `make target=linux' # linux
|
||||||
# `make target=djggp2' # djggp2 2.03
|
# `make target=djggp2' # dos32 - djggp2 2.03
|
||||||
# `make target=cygwin' # cygwin 1.1.x
|
# `make target=cygwin' # win32 - cygwin 1.3.x
|
||||||
# `make target=mingw32' # mingw32
|
# `make target=mingw32' # win32 - mingw32
|
||||||
# `make target=no-cygwin' # mingw32 as included in cygwin 1.1.x
|
# `make target=no-cygwin' # win32 - mingw32 as included in cygwin 1.3.x
|
||||||
# `make target=vc6' # Visual C++ 6.0
|
# `make target=bcc' # win32 - Borland C++ 5.5.1
|
||||||
|
# `make target=dmc' # win32 - Digital Mars C++ 8.30
|
||||||
|
# `make target=vc6' # win32 - Visual C++ 6.0
|
||||||
|
# `make target=wcc' # win32 - Watcom C++ 11.0c
|
||||||
|
# `make target=cross-m68k-linux' # m68k-linux cross compiler
|
||||||
|
# `make target=cross-mingw32' # i586-mingw32msvc cross compiler
|
||||||
|
# `make target=cross-mint' # m68k-atari-mint cross compiler
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
@@ -14,9 +21,11 @@
|
|||||||
|
|
||||||
ifeq ($(strip $(UCLDIR)),)
|
ifeq ($(strip $(UCLDIR)),)
|
||||||
# change this to reflect where the UCL library is
|
# change this to reflect where the UCL library is
|
||||||
UCLDIR = $(HOME)/local/src/ucl-0.92
|
UCLDIR = $(HOME)/local/src/ucl-1.01
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
##target =
|
||||||
|
|
||||||
DEBUG = 0
|
DEBUG = 0
|
||||||
|
|
||||||
|
|
||||||
@@ -28,23 +37,28 @@ SHELL = /bin/sh
|
|||||||
|
|
||||||
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
.SUFFIXES: .a .c .cpp .exe .lib .o .obj
|
.SUFFIXES: .a .c .cpp .exe .lib .o .obj .rc .res .ttp
|
||||||
|
|
||||||
|
|
||||||
srcdir = .
|
srcdir = .
|
||||||
top_srcdir = ..
|
top_srcdir = ..
|
||||||
|
|
||||||
|
VPATH = $(srcdir)
|
||||||
|
|
||||||
|
|
||||||
# auto-detect the target unless given on the commandline
|
# auto-detect the target unless given on the commandline
|
||||||
target = djgpp2
|
ifeq ($(strip $(target)),)
|
||||||
|
##target = djgpp2
|
||||||
ifneq ($(strip $(wildcard /usr/include/linux)),)
|
ifneq ($(strip $(wildcard /usr/include/linux)),)
|
||||||
target = linux
|
target = linux
|
||||||
endif
|
endif
|
||||||
ifneq ($(strip $(wildcard /platform/sun4?/kernel/unix)),)
|
##ifneq ($(strip $(wildcard /platform/sun4?/kernel/unix)),)
|
||||||
target = sparc
|
##target = sparc
|
||||||
|
##endif
|
||||||
endif
|
endif
|
||||||
ifeq ($(target),msc)
|
|
||||||
override target = vc6
|
ifeq ($(strip $(target)),)
|
||||||
|
include please_specify_a_target
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
@@ -59,15 +73,16 @@ override T = $(basename $@)
|
|||||||
# these use exceptions & RTTI
|
# these use exceptions & RTTI
|
||||||
OBJECTS1 = \
|
OBJECTS1 = \
|
||||||
compress$o except$o file$o lefile$o \
|
compress$o except$o file$o lefile$o \
|
||||||
filter$o mem$o msg$o stdcxx$o work$o ui$o \
|
filter$o linker$o mem$o msg$o stdcxx$o work$o ui$o \
|
||||||
packer$o packhead$o packmast$o \
|
packer$o packerf$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_com$o p_djgpp2$o p_elks$o p_exe$o \
|
||||||
p_sys$o p_tmt$o p_tos$o \
|
p_lx_elf$o p_lx_exc$o p_lx_sep$o p_lx_sh$o \
|
||||||
p_unix$o p_vmlinz$o p_w32pe$o p_wcle$o
|
p_ps1$o p_sys$o p_tmt$o p_tos$o \
|
||||||
|
p_unix$o p_vmlinz$o p_w16ne$o p_w32pe$o p_wcle$o
|
||||||
|
|
||||||
# no exceptions or RTTI
|
# no exceptions or RTTI
|
||||||
OBJECTS2 = \
|
OBJECTS2 = \
|
||||||
filteri$o help$o main$o mygetopt$o util$o linker$o \
|
filteri$o help$o main$o mygetopt$o snprintf$o util$o \
|
||||||
c_init$o c_file$o c_none$o c_screen$o \
|
c_init$o c_file$o c_none$o c_screen$o \
|
||||||
s_object$o s_djgpp2$o s_vcsa$o s_win32$o
|
s_object$o s_djgpp2$o s_vcsa$o s_win32$o
|
||||||
|
|
||||||
@@ -75,43 +90,58 @@ OBJECTS2 = \
|
|||||||
OBJECTS3 =
|
OBJECTS3 =
|
||||||
|
|
||||||
OBJECTS = $(OBJECTS1) $(OBJECTS2) $(OBJECTS3)
|
OBJECTS = $(OBJECTS1) $(OBJECTS2) $(OBJECTS3)
|
||||||
|
LIBS =
|
||||||
|
RESOURCES =
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
# // compiler settings
|
# // compiler settings
|
||||||
# ************************************************************************/
|
# ************************************************************************/
|
||||||
|
|
||||||
# default to a gcc unix-type compiler
|
###
|
||||||
CC = gcc
|
### default compiler (gcc under unix)
|
||||||
CXX = $(CC)
|
###
|
||||||
DEFS =
|
|
||||||
INCLUDES = -I$(srcdir)
|
|
||||||
CFLAGS_OUTPUT = -o $@
|
|
||||||
CXXFLAGS_OUTPUT = $(CFLAGS_OUTPUT)
|
|
||||||
|
|
||||||
LINK_EXE = $(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $@ $^ $(LDLIBS)
|
|
||||||
STUBEDIT_EXE =
|
|
||||||
|
|
||||||
o = .o
|
o = .o
|
||||||
a = .a
|
a = .a
|
||||||
e = .exe
|
e =
|
||||||
|
|
||||||
|
CC = gcc
|
||||||
|
DEFS =
|
||||||
|
INCLUDES =
|
||||||
|
##INCLUDES = -I. -I$(srcdir)
|
||||||
|
CFLAGS_OUTPUT = -o $@
|
||||||
|
|
||||||
|
LINK_EXE = $(CXXLD) $(LDFLAGS) -o $@ $^ $(LDLIBS)
|
||||||
|
STUBEDIT_EXE =
|
||||||
|
STUBIFY_EXE =
|
||||||
|
CHMOD_EXE =
|
||||||
|
|
||||||
|
# C++ defaults are set later
|
||||||
|
CXX =
|
||||||
|
CXXLD =
|
||||||
|
CXXFLAGS_OUTPUT =
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
### gcc defaults
|
### gcc defaults
|
||||||
###
|
###
|
||||||
|
|
||||||
##CFLAGS_O = -Os
|
|
||||||
CFLAGS_O = -O2
|
|
||||||
##CFLAGS_WERROR = -Werror
|
##CFLAGS_WERROR = -Werror
|
||||||
|
CFLAGS_WERROR =
|
||||||
CFLAGS_W = $(CFLAGS_WERROR)
|
CFLAGS_W = $(CFLAGS_WERROR)
|
||||||
CFLAGS_W += -Wall -W -Wcast-align -Wcast-qual -Wmissing-declarations -Wmissing-prototypes -Wshadow -Wwrite-strings
|
CFLAGS_W += -Wall -W -Wcast-align -Wcast-qual -Wmissing-prototypes -Wpointer-arith -Wshadow -Wwrite-strings
|
||||||
##CFLAGS_M = -fno-builtin
|
CFLAGS_M =
|
||||||
|
##CFLAGS_M += -fno-builtin
|
||||||
##CFLAGS_M += -malign-functions=0 -malign-jumps=0 -malign-loops=0
|
##CFLAGS_M += -malign-functions=0 -malign-jumps=0 -malign-loops=0
|
||||||
|
##CFLAGS_O = -Os -fstrict-aliasing
|
||||||
|
##CFLAGS_O = -O2 -fstrict-aliasing
|
||||||
|
CFLAGS_O = -O2 -fno-strict-aliasing
|
||||||
|
|
||||||
CFLAGS = $(CFLAGS_W) $(CFLAGS_O) $(CFLAGS_M)
|
CFLAGS = $(CFLAGS_W) $(CFLAGS_M) $(CFLAGS_O)
|
||||||
CXXFLAGS = $(CFLAGS) -Wsynth -fconserve-space
|
CXXFLAGS = $(CFLAGS) -Wsynth -fconserve-space
|
||||||
CXXFLAGS1 = $(CXXFLAGS)
|
CXXFLAGS1 = $(CXXFLAGS)
|
||||||
|
##CXXFLAGS1 += -fasynchronous-exceptions
|
||||||
CXXFLAGS2 = $(CXXFLAGS) -fno-exceptions -fno-rtti
|
CXXFLAGS2 = $(CXXFLAGS) -fno-exceptions -fno-rtti
|
||||||
|
|
||||||
ifeq ($(DEBUG),1)
|
ifeq ($(DEBUG),1)
|
||||||
@@ -125,9 +155,9 @@ else
|
|||||||
LDFLAGS = -s
|
LDFLAGS = -s
|
||||||
endif
|
endif
|
||||||
LDFLAGS += -Wl,-Map,$T.map
|
LDFLAGS += -Wl,-Map,$T.map
|
||||||
LDLIBS =
|
|
||||||
LDLIBS = -lz
|
LDLIBS = -lz
|
||||||
LIBDIRS =
|
LIBDIRS =
|
||||||
|
DOS_LDLIBS =
|
||||||
DOS_LIBDIRS =
|
DOS_LIBDIRS =
|
||||||
|
|
||||||
|
|
||||||
@@ -139,16 +169,17 @@ UCLDIR:=$(strip $(subst \,/,$(UCLDIR)))
|
|||||||
NRVDIR:=$(strip $(subst \,/,$(NRVDIR)))
|
NRVDIR:=$(strip $(subst \,/,$(NRVDIR)))
|
||||||
u = ucl
|
u = ucl
|
||||||
U = UCL
|
U = UCL
|
||||||
upx_exe = upx$e
|
upx_exe_tail =
|
||||||
include $(srcdir)/Makefile.inc
|
include $(srcdir)/Makefile.inc
|
||||||
ifneq ($(strip $(wildcard $(NRVDIR)/include/nrv)),)
|
ifneq ($(strip $(wildcard $(NRVDIR)/include/nrv)),)
|
||||||
u = nrv
|
u = nrv
|
||||||
U = NRV
|
U = NRV
|
||||||
upx_exe = upx_$u$e
|
upx_exe_tail = _$(u)
|
||||||
include $(srcdir)/Makefile.inc
|
include $(srcdir)/Makefile.inc
|
||||||
endif
|
endif
|
||||||
|
upx_exe = upx$(upx_exe_tail)$(e)
|
||||||
|
|
||||||
tmp := -Wl,--rpath,
|
override tmp := -Wl,--rpath,
|
||||||
LDRPATH := $(addprefix $(tmp),$(LIBDIRS))
|
LDRPATH := $(addprefix $(tmp),$(LIBDIRS))
|
||||||
LIBDIRS += .
|
LIBDIRS += .
|
||||||
LDLIBDIRS := $(addprefix -L,$(LIBDIRS))
|
LDLIBDIRS := $(addprefix -L,$(LIBDIRS))
|
||||||
@@ -158,17 +189,19 @@ LDFLAGS += $(LDLIBDIRS)
|
|||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
### linux/i386
|
### Linux
|
||||||
###
|
###
|
||||||
|
|
||||||
ifeq ($(target),linux)
|
ifeq ($(target),linux)
|
||||||
e =
|
override arch := $(shell uname -m | sed -e 's/^i[3456789]86$$/i386/')
|
||||||
###CC = /usr/local/packages/gcc-cvs/bin/g++
|
|
||||||
DEFS += '-DUPX_CONFIG_H="config_h/linux.h"'
|
DEFS += '-DUPX_CONFIG_H="config_h/linux.h"'
|
||||||
##CFLAGS_M += -mno-schedule-prologue
|
DEFS += -D_FILE_OFFSET_BITS=64
|
||||||
CFLAGS_M += -march=i386 -mcpu=pentium
|
|
||||||
CFLAGS_WERROR = -Werror
|
|
||||||
LDLIBS += -lmcheck
|
LDLIBS += -lmcheck
|
||||||
|
ifeq ($(arch),i386)
|
||||||
|
CC += -march=i386 -mcpu=i586
|
||||||
|
##CFLAGS_M += -mno-schedule-prologue
|
||||||
|
endif
|
||||||
|
##CFLAGS_WERROR = -Werror
|
||||||
|
|
||||||
ifeq (1,2) # checkergcc
|
ifeq (1,2) # checkergcc
|
||||||
CC = checkergcc
|
CC = checkergcc
|
||||||
@@ -176,25 +209,101 @@ ifeq (1,2) # checkergcc
|
|||||||
else
|
else
|
||||||
ifeq ($(DEBUG),1)
|
ifeq ($(DEBUG),1)
|
||||||
##CFLAGS += -O0 -gstabs+3
|
##CFLAGS += -O0 -gstabs+3
|
||||||
CFLAGS += -O0 -gdwarf-2
|
##CFLAGS += -O0 -gdwarf-2
|
||||||
|
CFLAGS += -O0 -g
|
||||||
else
|
else
|
||||||
##LDFLAGS += -static
|
##LDFLAGS += -static
|
||||||
STUBEDIT_EXE = objcopy -S -R .comment -R .note $@ && perl $(srcdir)/stub/scripts/brandelf.pl $@ && chmod 755 $@
|
STUBEDIT_EXE = objcopy -S -R .comment -R .note $@
|
||||||
|
ifeq ($(arch),i386)
|
||||||
|
STUBIFY_EXE = perl $(srcdir)/stub/scripts/brandelf.pl $@
|
||||||
|
CHMOD_EXE = chmod 755 $@
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
endif # linux
|
endif # linux
|
||||||
|
|
||||||
|
|
||||||
|
###
|
||||||
|
### Linux cross compilers
|
||||||
|
###
|
||||||
|
|
||||||
|
ifeq ($(target),cross-m68k-linux)
|
||||||
|
CC = m68k-linux-gcc
|
||||||
|
DEFS += '-DUPX_CONFIG_H="config_h/linux.h"'
|
||||||
|
##LDLIBS += -lmcheck
|
||||||
|
endif # cross-m68k-linux
|
||||||
|
|
||||||
|
|
||||||
|
###
|
||||||
|
### sparc-sun-solaris2.8
|
||||||
|
###
|
||||||
|
|
||||||
|
ifeq ($(target),sparc)
|
||||||
|
CC = gcc
|
||||||
|
DEFS += '-DUPX_CONFIG_H="config_h/sparc_sun_solaris28.h"'
|
||||||
|
endif # sparc
|
||||||
|
|
||||||
|
|
||||||
|
ifeq ($(target),XXX-sparc)
|
||||||
|
DEFS += '-DUPX_CONFIG_H="config_h/sparc_sun_solaris28.h"'
|
||||||
|
INCLUDES += -I/home/ethmola/local/include
|
||||||
|
|
||||||
|
ifeq (1,2) # native compiler
|
||||||
|
CFLAGS = -O0 -g
|
||||||
|
CXXFLAGS1 =
|
||||||
|
CXXFLAGS2 =
|
||||||
|
DEFS += -DUSE_STDNAMESPACE
|
||||||
|
else # gcc
|
||||||
|
CFLAGS += -O0 -gstabs+
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq (1,2) # purify
|
||||||
|
DEFS += -D__PURIFY__
|
||||||
|
CXXLD := purify $(CXXLD)
|
||||||
|
endif
|
||||||
|
|
||||||
|
endif # XXX-sparc
|
||||||
|
|
||||||
|
|
||||||
|
###
|
||||||
|
### Atari cross compiler
|
||||||
|
###
|
||||||
|
|
||||||
|
ifeq ($(target),cross-mint)
|
||||||
|
e = .ttp
|
||||||
|
CC = m68k-atari-mint-gcc
|
||||||
|
CC += -m68000
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(target),cross-mint-m68040)
|
||||||
|
e = .ttp
|
||||||
|
CC = m68k-atari-mint-gcc
|
||||||
|
CC += -m68040
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(target),cross-mint-m68020-60)
|
||||||
|
e = .ttp
|
||||||
|
CC = m68k-atari-mint-gcc
|
||||||
|
CC += -m68020-60 -m68881
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
### djgpp2
|
### djgpp2
|
||||||
###
|
###
|
||||||
|
|
||||||
ifeq ($(target),djgpp2)
|
ifeq ($(target),djgpp2)
|
||||||
CFLAGS_M += -mno-schedule-prologue
|
e = .exe
|
||||||
CFLAGS_M += -march=i386 -mcpu=pentium
|
CC += -march=i386 -mcpu=i586
|
||||||
|
##CFLAGS_M += -mno-schedule-prologue
|
||||||
CFLAGS_WERROR = -Werror
|
CFLAGS_WERROR = -Werror
|
||||||
STUBEDIT_EXE = stubedit $@ bufsize=0xfc00
|
STUBEDIT_EXE = stubedit $@ bufsize=0xfc00
|
||||||
|
ifneq ($(strip $(wildcard $(DJDIR)/bin/mfxdjstubify.ex[eE])),)
|
||||||
|
ifneq ($(strip $(wildcard $(DJDIR)/bin/cwsdstub.ex[eE])),)
|
||||||
|
STUBIFY_EXE = mfxdjstubify -v -s $(DJDIR)/bin/cwsdstub.exe $(upx_exe)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
endif # djgpp2
|
endif # djgpp2
|
||||||
|
|
||||||
|
|
||||||
@@ -203,113 +312,54 @@ endif # djgpp2
|
|||||||
###
|
###
|
||||||
|
|
||||||
ifeq ($(target),cygwin)
|
ifeq ($(target),cygwin)
|
||||||
CFLAGS_M += -mno-schedule-prologue
|
e = .exe
|
||||||
CFLAGS_M += -march=i386 -mcpu=pentium
|
CC += -march=i386 -mcpu=i586
|
||||||
CFLAGS_WERROR = -Werror
|
CXXLD = g++
|
||||||
|
##CFLAGS_M += -mno-schedule-prologue
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(target),mingw32)
|
ifeq ($(target),mingw32)
|
||||||
CFLAGS_M += -mno-schedule-prologue
|
e = .exe
|
||||||
CFLAGS_M += -march=i386 -mcpu=pentium
|
CC = gcc -mno-cygwin
|
||||||
|
CC += -march=i386 -mcpu=i586
|
||||||
|
CXXLD = g++ -mno-cygwin
|
||||||
|
##CFLAGS_M += -mno-schedule-prologue
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# mingw32 as included in cygwin
|
# mingw32 as included in cygwin
|
||||||
ifeq ($(target),no-cygwin)
|
ifeq ($(target),no-cygwin)
|
||||||
|
e = .exe
|
||||||
CC = gcc -mno-cygwin
|
CC = gcc -mno-cygwin
|
||||||
CFLAGS_M += -mno-schedule-prologue
|
CC += -march=i386 -mcpu=i586
|
||||||
CFLAGS_M += -march=i386 -mcpu=pentium
|
CXXLD = g++ -mno-cygwin
|
||||||
CFLAGS_WERROR = -Werror
|
##CFLAGS_M += -mno-schedule-prologue
|
||||||
|
endif
|
||||||
|
|
||||||
|
# mingw32 cross compiler
|
||||||
|
ifeq ($(target),cross-mingw32)
|
||||||
|
e = .exe
|
||||||
|
CC = i586-mingw32msvc-gcc
|
||||||
|
CC += -march=i386 -mcpu=i586
|
||||||
|
CXXLD = i586-mingw32msvc-g++
|
||||||
|
##CFLAGS_M += -mno-schedule-prologue
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
### Microsoft 32-bit C/C++ Compiler 12.00 (aka Visual C++ 6)
|
### Borland C++ 5.5.1
|
||||||
###
|
|
||||||
|
|
||||||
ifeq ($(target),vc6)
|
|
||||||
o = .obj
|
|
||||||
a = .lib
|
|
||||||
CC = cl -nologo
|
|
||||||
CFLAGS = -W4 -WX
|
|
||||||
CXXFLAGS1 = $(CFLAGS) -GR -GX -EHa
|
|
||||||
CXXFLAGS2 = $(CFLAGS)
|
|
||||||
LDFLAGS =
|
|
||||||
LINK_LDFLAGS = /link /map:$T.map
|
|
||||||
|
|
||||||
ifneq ($(strip $(DOS_LIBDIRS)),)
|
|
||||||
LIB := $(DOS_LIBDIRS);$(LIB)
|
|
||||||
endif
|
|
||||||
export LIB
|
|
||||||
|
|
||||||
ifeq (1,2)
|
|
||||||
# statically link libc.lib
|
|
||||||
CC += -ML
|
|
||||||
##LDLIBS = $(u)_s.lib zlib_s.lib setargv.obj
|
|
||||||
LDLIBS = $(u)_s.lib setargv.obj
|
|
||||||
else
|
|
||||||
# link against msvcrt.dll
|
|
||||||
CC += -MD
|
|
||||||
LDLIBS = $(DOS_LDLIBS) zlib.lib setargv.obj
|
|
||||||
endif
|
|
||||||
ifeq ($(DEBUG),1)
|
|
||||||
CFLAGS += -Od -ZI
|
|
||||||
LINK_LDFLAGS += /debug
|
|
||||||
else
|
|
||||||
CFLAGS += -O2 -GF
|
|
||||||
LINK_LDFLAGS += /release
|
|
||||||
endif
|
|
||||||
|
|
||||||
##LINK_LDFLAGS += /verbose
|
|
||||||
LINK_EXE = $(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) -Fe$@ $^ $(LDLIBS) $(LINK_LDFLAGS)
|
|
||||||
|
|
||||||
endif # vc6
|
|
||||||
|
|
||||||
|
|
||||||
###
|
|
||||||
### sparc
|
|
||||||
###
|
|
||||||
|
|
||||||
ifeq ($(target),sparc)
|
|
||||||
e =
|
|
||||||
DEFS += '-DUPX_CONFIG_H="config_h/sparc.h"'
|
|
||||||
INCLUDES += -I/home/ethmola/local/include
|
|
||||||
|
|
||||||
ifeq (1,2) # native compiler
|
|
||||||
CFLAGS = -O0 -g
|
|
||||||
CXXFLAGS1 =
|
|
||||||
CXXFLAGS2 =
|
|
||||||
CFLAGS_M =
|
|
||||||
DEFS += -DUSE_STDNAMESPACE
|
|
||||||
else # gcc
|
|
||||||
CFLAGS += -O0 -gstabs+
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq (1,2) # purify
|
|
||||||
DEFS += -D__PURIFY__
|
|
||||||
LDFLAGS = -g -L/home/ethmola/local/lib
|
|
||||||
LINK_EXE = purify $(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $@ $^ $(LDLIBS)
|
|
||||||
else
|
|
||||||
LDFLAGS += -g -L/home/ethmola/local/lib
|
|
||||||
LINK_EXE = $(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $@ $^ $(LDLIBS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
endif # sparc
|
|
||||||
|
|
||||||
|
|
||||||
###
|
|
||||||
### Borland C++ 5.5 (DOES NOT WORK - INCOMPLETE C++ IMPLEMENTATION)
|
|
||||||
###
|
###
|
||||||
|
|
||||||
ifeq ($(target),bcc)
|
ifeq ($(target),bcc)
|
||||||
o = .obj
|
o = .obj
|
||||||
a = .lib
|
a = .lib
|
||||||
CC = bcc32
|
e = .exe
|
||||||
CFLAGS = -w -w-par
|
CC = bcc32 -q
|
||||||
|
CFLAGS = -w -w-aus -g1
|
||||||
CXXFLAGS1 = $(CFLAGS)
|
CXXFLAGS1 = $(CFLAGS)
|
||||||
CXXFLAGS2 = $(CFLAGS)
|
CXXFLAGS2 = $(CFLAGS) -x- -xd- -RT-
|
||||||
CFLAGS_OUTPUT = -o$@
|
CFLAGS_OUTPUT = -o$@
|
||||||
LDFLAGS =
|
LDFLAGS =
|
||||||
LDLIBS = $(DOS_LDLIBS) zlib.lib
|
LDLIBS = $(DOS_LDLIBS) zlib114.lib
|
||||||
|
|
||||||
ifneq ($(strip $(DOS_LIBDIRS)),)
|
ifneq ($(strip $(DOS_LIBDIRS)),)
|
||||||
LIB := $(DOS_LIBDIRS);$(LIB)
|
LIB := $(DOS_LIBDIRS);$(LIB)
|
||||||
@@ -322,15 +372,136 @@ else
|
|||||||
CFLAGS += -O2 -d
|
CFLAGS += -O2 -d
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LINK_EXE = $(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) -e$@ $^ $(LDLIBS)
|
LINK_EXE = $(CXXLD) $(LDFLAGS) -e$@ $^ $(LDLIBS)
|
||||||
|
|
||||||
endif # bcc
|
endif # bcc
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
### malloc debuggers (Linux only)
|
### Digital Mars C++ 8.30
|
||||||
###
|
###
|
||||||
|
|
||||||
|
ifeq ($(target),dmc)
|
||||||
|
o = .obj
|
||||||
|
a = .lib
|
||||||
|
e = .exe
|
||||||
|
CC = dmc -mn
|
||||||
|
CFLAGS = -w- -wx
|
||||||
|
CXXFLAGS1 = $(CFLAGS) -Aa -Ab -Ae -Ar
|
||||||
|
CXXFLAGS2 = $(CFLAGS) -Aa -Ab
|
||||||
|
CFLAGS_OUTPUT = -o$@
|
||||||
|
LDFLAGS =
|
||||||
|
LDLIBS = $(DOS_LDLIBS)
|
||||||
|
|
||||||
|
ifneq ($(strip $(DOS_LIBDIRS)),)
|
||||||
|
LIB := $(DOS_LIBDIRS);$(LIB)
|
||||||
|
endif
|
||||||
|
export LIB
|
||||||
|
|
||||||
|
ifeq ($(DEBUG),1)
|
||||||
|
CFLAGS += -o- -g -s
|
||||||
|
else
|
||||||
|
CFLAGS += -o
|
||||||
|
endif
|
||||||
|
|
||||||
|
LINK_EXE = $(CXXLD) $(LDFLAGS) -o$@ $^ $(LDLIBS)
|
||||||
|
|
||||||
|
endif # dmc
|
||||||
|
|
||||||
|
|
||||||
|
###
|
||||||
|
### Visual C++ 6 (aka Microsoft C/C++ Compiler 12.00)
|
||||||
|
###
|
||||||
|
|
||||||
|
ifeq ($(target),vc6)
|
||||||
|
o = .obj
|
||||||
|
a = .lib
|
||||||
|
e = .exe
|
||||||
|
CC = cl -nologo
|
||||||
|
CFLAGS = -W4 -WX
|
||||||
|
CXXFLAGS1 = $(CFLAGS) -EHac -GR
|
||||||
|
CXXFLAGS2 = $(CFLAGS)
|
||||||
|
LDFLAGS =
|
||||||
|
LINK_LDFLAGS = /link /map:$T.map
|
||||||
|
|
||||||
|
ifneq ($(strip $(DOS_LIBDIRS)),)
|
||||||
|
LIB := $(DOS_LIBDIRS);$(LIB)
|
||||||
|
endif
|
||||||
|
export LIB
|
||||||
|
|
||||||
|
ifeq (1,2)
|
||||||
|
# statically link libc.lib
|
||||||
|
CC += -ML
|
||||||
|
LDLIBS = $(u)_s.lib setargv.obj
|
||||||
|
else
|
||||||
|
# link against msvcrt.dll
|
||||||
|
CC += -MD
|
||||||
|
LDLIBS = $(DOS_LDLIBS) zlib114.lib setargv.obj
|
||||||
|
endif
|
||||||
|
ifeq ($(DEBUG),1)
|
||||||
|
CFLAGS += -Od -ZI
|
||||||
|
LINK_LDFLAGS += /debug
|
||||||
|
else
|
||||||
|
CFLAGS += -O2 -GF
|
||||||
|
LINK_LDFLAGS += /release
|
||||||
|
endif
|
||||||
|
RESOURCES = upx.res
|
||||||
|
|
||||||
|
##LINK_LDFLAGS += /verbose
|
||||||
|
LINK_EXE = $(CXXLD) $(LDFLAGS) -Fe$@ $^ $(LDLIBS) $(LINK_LDFLAGS)
|
||||||
|
|
||||||
|
endif # vc6
|
||||||
|
|
||||||
|
|
||||||
|
###
|
||||||
|
### Watcom C++ 11.0c
|
||||||
|
###
|
||||||
|
|
||||||
|
ifeq ($(target),wcc)
|
||||||
|
o = .obj
|
||||||
|
a = .lib
|
||||||
|
e = .exe
|
||||||
|
CC = wcl386 -zq -bt=nt -mf -5r
|
||||||
|
CFLAGS = -zc -w5 -we
|
||||||
|
CXXFLAGS1 = $(CFLAGS) -xs -xr
|
||||||
|
CXXFLAGS2 = $(CFLAGS)
|
||||||
|
CFLAGS_OUTPUT = -fo=$@
|
||||||
|
LDFLAGS = -k0x100000 -fm
|
||||||
|
LDLIBS = $(DOS_LDLIBS)
|
||||||
|
|
||||||
|
INCLUDES:=$(strip $(subst /,\\,$(INCLUDES)))
|
||||||
|
ifeq (1,2)
|
||||||
|
WCL386:=$(INCLUDES)
|
||||||
|
export WCL386
|
||||||
|
INCLUDES:=
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(strip $(DOS_LIBDIRS)),)
|
||||||
|
LIB := $(DOS_LIBDIRS);$(LIB)
|
||||||
|
endif
|
||||||
|
export LIB
|
||||||
|
|
||||||
|
ifeq ($(DEBUG),1)
|
||||||
|
CFLAGS +=
|
||||||
|
else
|
||||||
|
# note: it seems that the optimizer is generating bad code with `-ox'
|
||||||
|
CFLAGS += -olr
|
||||||
|
endif
|
||||||
|
|
||||||
|
LINK_EXE = $(CXXLD) $(LDFLAGS) -fe=$@ $^ $(LDLIBS)
|
||||||
|
|
||||||
|
endif # wcc
|
||||||
|
|
||||||
|
|
||||||
|
# /***********************************************************************
|
||||||
|
# // malloc debuggers and memory checkers - somewhat obsolete, use valgrind
|
||||||
|
# ************************************************************************/
|
||||||
|
|
||||||
|
ifeq (1,2)
|
||||||
|
# compile in extra valgrind support
|
||||||
|
CFLAGS += -DWITH_VALGRIND
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq (1,2)
|
ifeq (1,2)
|
||||||
LDLIBS += -lefence
|
LDLIBS += -lefence
|
||||||
endif
|
endif
|
||||||
@@ -347,10 +518,43 @@ ifeq (1,2)
|
|||||||
##LDFLAGS += -Wl,-defsym,_DYNAMIC=0
|
##LDFLAGS += -Wl,-defsym,_DYNAMIC=0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq (1,2)
|
|
||||||
CFLAGS += -DWITH_MSS
|
# /***********************************************************************
|
||||||
LDLIBS += -lmss
|
# // finish settings
|
||||||
|
# ************************************************************************/
|
||||||
|
|
||||||
|
# C++ defaults
|
||||||
|
ifeq ($(strip $(CXX)),)
|
||||||
|
ifeq ($(strip $(CC)),gcc)
|
||||||
|
CXX = g++
|
||||||
|
else
|
||||||
|
CXX = $(CC)
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
ifeq ($(strip $(CXXLD)),)
|
||||||
|
CXXLD = $(CXX)
|
||||||
|
endif
|
||||||
|
ifeq ($(strip $(CXXFLAGS_OUTPUT)),)
|
||||||
|
CXXFLAGS_OUTPUT = $(CFLAGS_OUTPUT)
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
# extra flags
|
||||||
|
DEFS += $(EXTRA_DEFS)
|
||||||
|
CFLAGS += $(EXTRA_CFLAGS)
|
||||||
|
CFLAGS_W += $(EXTRA_CFLAGS_W)
|
||||||
|
CFLAGS_M += $(EXTRA_CFLAGS_M)
|
||||||
|
CFLAGS_O += $(EXTRA_CFLAGS_O)
|
||||||
|
CXXFLAGS1 += $(EXTRA_CXXFLAGS1)
|
||||||
|
CXXFLAGS2 += $(EXTRA_CXXFLAGS2)
|
||||||
|
LDFLAGS += $(EXTRA_LDFLAGS)
|
||||||
|
LDLIBS += $(EXTRA_LDLIBS)
|
||||||
|
|
||||||
|
|
||||||
|
# To better deal with asynchronous exceptions we compile all source
|
||||||
|
# files with exception handling and RTTI enabled - the size overhead
|
||||||
|
# is negligible.
|
||||||
|
CXXFLAGS2 = $(CXXFLAGS1)
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
@@ -359,37 +563,23 @@ endif
|
|||||||
|
|
||||||
all: $(upx_exe)
|
all: $(upx_exe)
|
||||||
|
|
||||||
.PHONY: all unupx mostlyclean clean distclean maintainer-clean untabify tags
|
.PHONY: all mostlyclean clean distclean maintainer-clean untabify tags
|
||||||
|
|
||||||
$(upx_exe): $(OBJECTS) $(LIBS)
|
$(upx_exe): $(OBJECTS) $(LIBS) $(RESOURCES)
|
||||||
$(LINK_EXE)
|
$(LINK_EXE)
|
||||||
$(STUBEDIT_EXE)
|
$(STUBEDIT_EXE)
|
||||||
|
$(STUBIFY_EXE)
|
||||||
|
$(CHMOD_EXE)
|
||||||
ifeq ($(target),djgpp2)
|
|
||||||
cwsbind: $(upx_exe)
|
|
||||||
-rm -f $T.cof
|
|
||||||
$(upx_exe) -1 --coff -o $T.cof $(upx_exe)
|
|
||||||
cat $(DJDIR)/bin/cwsdstub.exe $T.cof > $(upx_exe)
|
|
||||||
$(upx_exe) -d $(upx_exe)
|
|
||||||
$(upx_exe) --best $(upx_exe)
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
unupx:
|
|
||||||
$(MAKE) target=vc6 unupx.dll
|
|
||||||
|
|
||||||
unupx.dll: $(OBJECTS) $(LIBS)
|
|
||||||
$(LINK_DLL)
|
|
||||||
|
|
||||||
|
|
||||||
mostlyclean:
|
mostlyclean:
|
||||||
-rm -f *.d *.err *.i *.log *.map *~ gdb-trans*
|
-rm -f *.d *.err *.i *.log *.map *~ gdb-trans*
|
||||||
|
|
||||||
clean: mostlyclean
|
clean: mostlyclean
|
||||||
-rm -f *.a *.lib *.o *.obj tags TAGS ID
|
-rm -f *.a *.lib *.o *.obj *.res *.tds tags TAGS ID
|
||||||
-rm -f *.idb *.pdb
|
-rm -f *.idb *.pdb
|
||||||
-rm -f upx upx.exe upx_nrv upx_nrv.exe upx_ucl upx_ucl.exe
|
-rm -f $(upx_exe) upx upx.exe upx.ttp upx_nrv upx_nrv.exe upx_nrv.ttp upx_ucl upx_ucl.exe upx_ucl.ttp
|
||||||
|
-rm -rf .deps
|
||||||
|
|
||||||
distclean: clean
|
distclean: clean
|
||||||
|
|
||||||
@@ -411,72 +601,25 @@ ID:
|
|||||||
# // rules
|
# // rules
|
||||||
# ************************************************************************/
|
# ************************************************************************/
|
||||||
|
|
||||||
.c$o:
|
%$o : %.c
|
||||||
$(CC) $(DEFS) $(INCLUDES) $(CFLAGS) $(CFLAGS_OUTPUT) -c $<
|
$(CC) $(DEFS) $(INCLUDES) $(CFLAGS) $(CFLAGS_OUTPUT) -c $<
|
||||||
|
|
||||||
.cpp$o:
|
%$o : %.cpp
|
||||||
$(CXX) $(DEFS) $(INCLUDES) $(CXXFLAGS1) $(CXXFLAGS_OUTPUT) -c $<
|
|
||||||
|
|
||||||
$(OBJECTS1): %$o : %.cpp
|
|
||||||
$(CXX) $(DEFS) $(INCLUDES) $(CXXFLAGS1) $(CXXFLAGS_OUTPUT) -c $<
|
$(CXX) $(DEFS) $(INCLUDES) $(CXXFLAGS1) $(CXXFLAGS_OUTPUT) -c $<
|
||||||
|
|
||||||
|
ifneq ($(strip $(OBJECTS2)),)
|
||||||
$(OBJECTS2): %$o : %.cpp
|
$(OBJECTS2): %$o : %.cpp
|
||||||
$(CXX) $(DEFS) $(INCLUDES) $(CXXFLAGS2) $(CXXFLAGS_OUTPUT) -c $<
|
$(CXX) $(DEFS) $(INCLUDES) $(CXXFLAGS2) $(CXXFLAGS_OUTPUT) -c $<
|
||||||
|
|
||||||
ifneq ($(strip $(OBJECTS3)),)
|
|
||||||
$(OBJECTS3): %$o : %.c
|
|
||||||
$(CC) $(DEFS) $(INCLUDES) $(CFLAGS) $(CFLAGS_OUTPUT) -c $<
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
%.res : %.rc
|
||||||
|
rc -l 0x409 -fo$@ $<
|
||||||
|
|
||||||
|
|
||||||
# /***********************************************************************
|
# /***********************************************************************
|
||||||
# // dependencies
|
# // dependencies
|
||||||
# ************************************************************************/
|
# ************************************************************************/
|
||||||
|
|
||||||
# FIXME: use automated dependencies
|
include $(srcdir)/Makefile.dep
|
||||||
|
|
||||||
main$o: mygetopt.h version.h
|
|
||||||
filter$o: filter.h
|
|
||||||
filteri$o: filter.h fcto_ml.ch fcto_ml2.ch fcto_ml3.ch
|
|
||||||
help$o: version.h
|
|
||||||
msg$o: ui.h
|
|
||||||
lefile$o: lefile.h
|
|
||||||
linker$o: linker.h
|
|
||||||
mygetopt$o: mygetopt.h
|
|
||||||
packer$o: packer.h filter.h linker.h ui.h version.h
|
|
||||||
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_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
|
|
||||||
|
|
||||||
p_com$o: packer.h p_com.h \
|
|
||||||
stub/l_com.h
|
|
||||||
p_djgpp2$o: packer.h p_djgpp2.h stub/stubify.h \
|
|
||||||
stub/l_djgpp2.h
|
|
||||||
p_exe$o: packer.h p_exe.h \
|
|
||||||
stub/l_exe.h
|
|
||||||
p_lx_elf$o: packer.h p_lx_elf.h p_unix.h p_elf.h \
|
|
||||||
stub/l_le_n2b.h stub/l_le_n2d.h
|
|
||||||
p_lx_sep$o: packer.h p_lx_sep.h p_lx_elf.h p_unix.h p_elf.h
|
|
||||||
p_lx_sh$o: packer.h p_lx_sh.h p_lx_elf.h p_unix.h p_elf.h \
|
|
||||||
stub/l_sh_n2b.h stub/l_sh_n2d.h
|
|
||||||
p_sys$o: packer.h p_sys.h p_com.h \
|
|
||||||
stub/l_sys.h
|
|
||||||
p_tmt$o: packer.h p_tmt.h \
|
|
||||||
stub/l_tmt.h
|
|
||||||
p_tos$o: packer.h p_tos.h \
|
|
||||||
stub/l_t_n2b.h stub/l_t_n2bs.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_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
|
|
||||||
|
|
||||||
# vi:nowrap
|
# vi:nowrap
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
# /***********************************************************************
|
||||||
|
# // automated dependencies
|
||||||
|
# ************************************************************************/
|
||||||
|
|
||||||
|
CFLAGS += -Wp,-MMD,.deps/$(*F).pp
|
||||||
|
|
||||||
|
ifeq ($(strip $(wildcard .deps)),)
|
||||||
|
DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
|
||||||
|
else
|
||||||
|
DEP_FILES := $(wildcard .deps/*.pp)
|
||||||
|
ifneq ($(strip $(DEP_FILES)),)
|
||||||
|
include $(DEP_FILES)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
+5
-3
@@ -1,11 +1,12 @@
|
|||||||
UDIR := $($(U)DIR)
|
UDIR := $($(U)DIR)
|
||||||
|
|
||||||
|
ifneq ($(strip $(wildcard $(UDIR)/include)),) # { include
|
||||||
DEFS += -DWITH_$(U)
|
DEFS += -DWITH_$(U)
|
||||||
|
|
||||||
ifneq ($(strip $(wildcard $(UDIR)/include)),)
|
|
||||||
INCLUDES += -I$(UDIR)/include
|
INCLUDES += -I$(UDIR)/include
|
||||||
endif
|
|
||||||
|
|
||||||
|
ifneq ($(strip $(wildcard $(UDIR)/build/$(target)/src/.libs)),)
|
||||||
|
LIBDIRS += $(UDIR)/build/$(target)/src/.libs
|
||||||
|
endif
|
||||||
ifneq ($(strip $(wildcard $(UDIR)/src/.libs)),)
|
ifneq ($(strip $(wildcard $(UDIR)/src/.libs)),)
|
||||||
LIBDIRS += $(UDIR)/src/.libs
|
LIBDIRS += $(UDIR)/src/.libs
|
||||||
endif
|
endif
|
||||||
@@ -35,3 +36,4 @@ LIBDIRS := $(LIBDIRS)
|
|||||||
LDLIBS := $(LDLIBS)
|
LDLIBS := $(LDLIBS)
|
||||||
DOS_LDLIBS := $(DOS_LDLIBS)
|
DOS_LDLIBS := $(DOS_LDLIBS)
|
||||||
|
|
||||||
|
endif # } include
|
||||||
|
|||||||
+149
-38
@@ -1,9 +1,9 @@
|
|||||||
/* bele.h --
|
/* bele.h -- access memory in BigEndian and LittleEndian byte order
|
||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -31,29 +31,48 @@
|
|||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// access memory in BigEndian and LittleEndian byte order
|
// core
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
inline unsigned short get_be16(const void *bb, int off=0)
|
inline unsigned get_be16(const void *bb)
|
||||||
{
|
{
|
||||||
const upx_bytep const b = reinterpret_cast<const upx_bytep>(bb) + off;
|
const upx_bytep b = (const upx_bytep) bb;
|
||||||
unsigned v;
|
unsigned v;
|
||||||
v = (unsigned) b[1] << 0;
|
v = (unsigned) b[1] << 0;
|
||||||
v |= (unsigned) b[0] << 8;
|
v |= (unsigned) b[0] << 8;
|
||||||
return (unsigned short) v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void set_be16(void *bb, unsigned v, int off=0)
|
inline void set_be16(void *bb, unsigned v)
|
||||||
{
|
{
|
||||||
upx_bytep const b = reinterpret_cast<upx_bytep>(bb) + off;
|
upx_bytep b = (upx_bytep) bb;
|
||||||
b[1] = (unsigned char) (v >> 0);
|
b[1] = (unsigned char) (v >> 0);
|
||||||
b[0] = (unsigned char) (v >> 8);
|
b[0] = (unsigned char) (v >> 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline unsigned get_be32(const void *bb, int off=0)
|
inline unsigned get_be24(const void *bb)
|
||||||
{
|
{
|
||||||
const upx_bytep const b = reinterpret_cast<const upx_bytep>(bb) + off;
|
const upx_bytep b = (const upx_bytep) bb;
|
||||||
|
unsigned v;
|
||||||
|
v = (unsigned) b[2] << 0;
|
||||||
|
v |= (unsigned) b[1] << 8;
|
||||||
|
v |= (unsigned) b[0] << 16;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void set_be24(void *bb, unsigned v)
|
||||||
|
{
|
||||||
|
upx_bytep b = (upx_bytep) bb;
|
||||||
|
b[2] = (unsigned char) (v >> 0);
|
||||||
|
b[1] = (unsigned char) (v >> 8);
|
||||||
|
b[0] = (unsigned char) (v >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline unsigned get_be32(const void *bb)
|
||||||
|
{
|
||||||
|
const upx_bytep b = (const upx_bytep) bb;
|
||||||
unsigned v;
|
unsigned v;
|
||||||
v = (unsigned) b[3] << 0;
|
v = (unsigned) b[3] << 0;
|
||||||
v |= (unsigned) b[2] << 8;
|
v |= (unsigned) b[2] << 8;
|
||||||
@@ -62,9 +81,9 @@ inline unsigned get_be32(const void *bb, int off=0)
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void set_be32(void *bb, unsigned v, int off=0)
|
inline void set_be32(void *bb, unsigned v)
|
||||||
{
|
{
|
||||||
upx_bytep const b = reinterpret_cast<upx_bytep>(bb) + off;
|
upx_bytep b = (upx_bytep) bb;
|
||||||
b[3] = (unsigned char) (v >> 0);
|
b[3] = (unsigned char) (v >> 0);
|
||||||
b[2] = (unsigned char) (v >> 8);
|
b[2] = (unsigned char) (v >> 8);
|
||||||
b[1] = (unsigned char) (v >> 16);
|
b[1] = (unsigned char) (v >> 16);
|
||||||
@@ -72,34 +91,34 @@ inline void set_be32(void *bb, unsigned v, int off=0)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline unsigned short get_le16(const void *bb, int off=0)
|
inline unsigned get_le16(const void *bb)
|
||||||
{
|
{
|
||||||
const upx_bytep const b = reinterpret_cast<const upx_bytep>(bb) + off;
|
|
||||||
unsigned v;
|
|
||||||
#if defined(__i386__)
|
#if defined(__i386__)
|
||||||
v = * (const unsigned short *) b;
|
return * (const unsigned short *) bb;
|
||||||
#else
|
#else
|
||||||
|
const upx_bytep b = (const upx_bytep) bb;
|
||||||
|
unsigned v;
|
||||||
v = (unsigned) b[0] << 0;
|
v = (unsigned) b[0] << 0;
|
||||||
v |= (unsigned) b[1] << 8;
|
v |= (unsigned) b[1] << 8;
|
||||||
|
return v;
|
||||||
#endif
|
#endif
|
||||||
return (unsigned short) v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void set_le16(void *bb, unsigned v, int off=0)
|
inline void set_le16(void *bb, unsigned v)
|
||||||
{
|
{
|
||||||
upx_bytep const b = reinterpret_cast<upx_bytep>(bb) + off;
|
|
||||||
#if defined(__i386__)
|
#if defined(__i386__)
|
||||||
(* (unsigned short *) b) = (unsigned short) v;
|
(* (unsigned short *) bb) = (unsigned short) (v & 0xffff);
|
||||||
#else
|
#else
|
||||||
|
upx_bytep b = (upx_bytep) bb;
|
||||||
b[0] = (unsigned char) (v >> 0);
|
b[0] = (unsigned char) (v >> 0);
|
||||||
b[1] = (unsigned char) (v >> 8);
|
b[1] = (unsigned char) (v >> 8);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline unsigned get_le24(const void *bb, int off=0)
|
inline unsigned get_le24(const void *bb)
|
||||||
{
|
{
|
||||||
const upx_bytep const b = reinterpret_cast<const upx_bytep>(bb) + off;
|
const upx_bytep b = (const upx_bytep) bb;
|
||||||
unsigned v;
|
unsigned v;
|
||||||
v = (unsigned) b[0] << 0;
|
v = (unsigned) b[0] << 0;
|
||||||
v |= (unsigned) b[1] << 8;
|
v |= (unsigned) b[1] << 8;
|
||||||
@@ -107,36 +126,36 @@ inline unsigned get_le24(const void *bb, int off=0)
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void set_le24(void *bb, unsigned v, int off=0)
|
inline void set_le24(void *bb, unsigned v)
|
||||||
{
|
{
|
||||||
upx_bytep const b = reinterpret_cast<upx_bytep>(bb) + off;
|
upx_bytep b = (upx_bytep) bb;
|
||||||
b[0] = (unsigned char) (v >> 0);
|
b[0] = (unsigned char) (v >> 0);
|
||||||
b[1] = (unsigned char) (v >> 8);
|
b[1] = (unsigned char) (v >> 8);
|
||||||
b[2] = (unsigned char) (v >> 16);
|
b[2] = (unsigned char) (v >> 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline unsigned get_le32(const void *bb, int off=0)
|
inline unsigned get_le32(const void *bb)
|
||||||
{
|
{
|
||||||
const upx_bytep const b = reinterpret_cast<const upx_bytep>(bb) + off;
|
|
||||||
unsigned v;
|
|
||||||
#if defined(__i386__)
|
#if defined(__i386__)
|
||||||
v = * (const unsigned *) b;
|
return * (const unsigned *) bb;
|
||||||
#else
|
#else
|
||||||
|
const upx_bytep b = (const upx_bytep) bb;
|
||||||
|
unsigned v;
|
||||||
v = (unsigned) b[0] << 0;
|
v = (unsigned) b[0] << 0;
|
||||||
v |= (unsigned) b[1] << 8;
|
v |= (unsigned) b[1] << 8;
|
||||||
v |= (unsigned) b[2] << 16;
|
v |= (unsigned) b[2] << 16;
|
||||||
v |= (unsigned) b[3] << 24;
|
v |= (unsigned) b[3] << 24;
|
||||||
#endif
|
|
||||||
return v;
|
return v;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void set_le32(void *bb, unsigned v, int off=0)
|
inline void set_le32(void *bb, unsigned v)
|
||||||
{
|
{
|
||||||
upx_bytep const b = reinterpret_cast<upx_bytep>(bb) + off;
|
|
||||||
#if defined(__i386__)
|
#if defined(__i386__)
|
||||||
(* (unsigned *) b) = v;
|
(* (unsigned *) bb) = v;
|
||||||
#else
|
#else
|
||||||
|
upx_bytep b = (upx_bytep) bb;
|
||||||
b[0] = (unsigned char) (v >> 0);
|
b[0] = (unsigned char) (v >> 0);
|
||||||
b[1] = (unsigned char) (v >> 8);
|
b[1] = (unsigned char) (v >> 8);
|
||||||
b[2] = (unsigned char) (v >> 16);
|
b[2] = (unsigned char) (v >> 16);
|
||||||
@@ -145,6 +164,54 @@ inline void set_le32(void *bb, unsigned v, int off=0)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// get signed values, i.e. sign-extend
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
inline int sign_extend(int v, int bits)
|
||||||
|
{
|
||||||
|
const int sign_bit = 1 << (bits - 1);
|
||||||
|
v |= -(v & sign_bit);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int get_be16_signed(const void *bb)
|
||||||
|
{
|
||||||
|
int v = get_be16(bb);
|
||||||
|
return sign_extend(v, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int get_be24_signed(const void *bb)
|
||||||
|
{
|
||||||
|
int v = get_be24(bb);
|
||||||
|
return sign_extend(v, 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int get_be32_signed(const void *bb)
|
||||||
|
{
|
||||||
|
int v = get_be32(bb);
|
||||||
|
return sign_extend(v, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int get_le16_signed(const void *bb)
|
||||||
|
{
|
||||||
|
int v = get_le16(bb);
|
||||||
|
return sign_extend(v, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int get_le24_signed(const void *bb)
|
||||||
|
{
|
||||||
|
int v = get_le24(bb);
|
||||||
|
return sign_extend(v, 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int get_le32_signed(const void *bb)
|
||||||
|
{
|
||||||
|
int v = get_le32(bb);
|
||||||
|
return sign_extend(v, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// classes for portable unaligned access
|
// classes for portable unaligned access
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
@@ -163,7 +230,8 @@ public:
|
|||||||
BE16& operator |= (unsigned v) { set_be16(d, get_be16(d) | v); return *this; }
|
BE16& operator |= (unsigned v) { set_be16(d, get_be16(d) | v); return *this; }
|
||||||
|
|
||||||
operator const unsigned () const { return get_be16(d); }
|
operator const unsigned () const { return get_be16(d); }
|
||||||
};
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
|
|
||||||
class BE32
|
class BE32
|
||||||
@@ -180,7 +248,8 @@ public:
|
|||||||
BE32& operator |= (unsigned v) { set_be32(d, get_be32(d) | v); return *this; }
|
BE32& operator |= (unsigned v) { set_be32(d, get_be32(d) | v); return *this; }
|
||||||
|
|
||||||
operator const unsigned () const { return get_be32(d); }
|
operator const unsigned () const { return get_be32(d); }
|
||||||
};
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
|
|
||||||
class LE16
|
class LE16
|
||||||
@@ -197,7 +266,8 @@ public:
|
|||||||
LE16& operator |= (unsigned v) { set_le16(d, get_le16(d) | v); return *this; }
|
LE16& operator |= (unsigned v) { set_le16(d, get_le16(d) | v); return *this; }
|
||||||
|
|
||||||
operator const unsigned () const { return get_le16(d); }
|
operator const unsigned () const { return get_le16(d); }
|
||||||
};
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
|
|
||||||
class LE32
|
class LE32
|
||||||
@@ -214,7 +284,8 @@ public:
|
|||||||
LE32& operator |= (unsigned v) { set_le32(d, get_le32(d) | v); return *this; }
|
LE32& operator |= (unsigned v) { set_le32(d, get_le32(d) | v); return *this; }
|
||||||
|
|
||||||
operator const unsigned () const { return get_le32(d); }
|
operator const unsigned () const { return get_le32(d); }
|
||||||
};
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
@@ -242,15 +313,55 @@ inline bool operator < (const LE32& v1, const LE32& v2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline T* operator + (T* ptr, const BE16& v) { return ptr + (const unsigned) v; }
|
||||||
|
template <class T>
|
||||||
|
inline T* operator - (T* ptr, const BE16& v) { return ptr - (const unsigned) v; }
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline T* operator + (T* ptr, const BE32& v) { return ptr + (const unsigned) v; }
|
||||||
|
template <class T>
|
||||||
|
inline T* operator - (T* ptr, const BE32& v) { return ptr - (const unsigned) v; }
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline T* operator + (T* ptr, const LE16& v) { return ptr + (const unsigned) v; }
|
||||||
|
template <class T>
|
||||||
|
inline T* operator - (T* ptr, const LE16& v) { return ptr - (const unsigned) v; }
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline T* operator + (T* ptr, const LE32& v) { return ptr + (const unsigned) v; }
|
||||||
|
template <class T>
|
||||||
|
inline T* operator - (T* ptr, const LE32& v) { return ptr - (const unsigned) v; }
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// misc
|
// misc
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
// for use with qsort()
|
// for use with qsort()
|
||||||
int be16_compare(const void *e1, const void *e2);
|
int be16_compare(const void *e1, const void *e2);
|
||||||
|
int be24_compare(const void *e1, const void *e2);
|
||||||
int be32_compare(const void *e1, const void *e2);
|
int be32_compare(const void *e1, const void *e2);
|
||||||
int le16_compare(const void *e1, const void *e2);
|
int le16_compare(const void *e1, const void *e2);
|
||||||
|
int le24_compare(const void *e1, const void *e2);
|
||||||
int le32_compare(const void *e1, const void *e2);
|
int le32_compare(const void *e1, const void *e2);
|
||||||
|
int be16_compare_signed(const void *e1, const void *e2);
|
||||||
|
int be24_compare_signed(const void *e1, const void *e2);
|
||||||
|
int be32_compare_signed(const void *e1, const void *e2);
|
||||||
|
int le16_compare_signed(const void *e1, const void *e2);
|
||||||
|
int le24_compare_signed(const void *e1, const void *e2);
|
||||||
|
int le32_compare_signed(const void *e1, const void *e2);
|
||||||
|
|
||||||
|
|
||||||
|
// just for testing...
|
||||||
|
#if 0 && defined(__i386__) && defined(__GNUC_VERSION_HEX__)
|
||||||
|
# if (__GNUC_VERSION_HEX__ >= 0x030100)
|
||||||
|
typedef unsigned short LE16_unaligned __attribute__((__packed__,__aligned__(1)));
|
||||||
|
typedef unsigned int LE32_unaligned __attribute__((__packed__,__aligned__(1)));
|
||||||
|
# define LE16 LE16_unaligned
|
||||||
|
# define LE32 LE32_unaligned
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif /* already included */
|
#endif /* already included */
|
||||||
|
|||||||
+4
-4
@@ -1,9 +1,9 @@
|
|||||||
/* c_file.cpp -- file console output
|
/* c_file.cpp --
|
||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -1,9 +1,9 @@
|
|||||||
/* c_init.cpp -- console initialization
|
/* c_init.cpp --
|
||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -1,9 +1,9 @@
|
|||||||
/* c_none.cpp -- dummy console output
|
/* c_none.cpp --
|
||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -196,7 +196,7 @@ static void print0(FILE *f, const char *ss)
|
|||||||
|
|
||||||
// Note:
|
// Note:
|
||||||
// We use 2 passes to avoid unnecessary system calls because
|
// We use 2 passes to avoid unnecessary system calls because
|
||||||
// scrollUp() under Win95/98 is *extremely* slow.
|
// scrollUp() under Win32 is *extremely* slow.
|
||||||
UNUSED(f);
|
UNUSED(f);
|
||||||
|
|
||||||
screen->getCursor(screen,&old_cx,&old_cy);
|
screen->getCursor(screen,&old_cx,&old_cy);
|
||||||
|
|||||||
+242
@@ -0,0 +1,242 @@
|
|||||||
|
/* compress.ch --
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#if defined(upx_adler32)
|
||||||
|
unsigned upx_adler32(const void *buf, unsigned len, unsigned adler)
|
||||||
|
{
|
||||||
|
if (len == 0)
|
||||||
|
return adler;
|
||||||
|
assert(buf != NULL);
|
||||||
|
return ucl_adler32(adler, (const ucl_bytep)buf, len);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(upx_crc32)
|
||||||
|
unsigned upx_crc32(const void *buf, unsigned len, unsigned crc)
|
||||||
|
{
|
||||||
|
if (len == 0)
|
||||||
|
return crc;
|
||||||
|
assert(buf != NULL);
|
||||||
|
return ucl_crc32(crc, (const ucl_bytep)buf, len);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#if defined(upx_compress)
|
||||||
|
|
||||||
|
int upx_compress ( const upx_bytep src, upx_uint src_len,
|
||||||
|
upx_bytep dst, upx_uintp dst_len,
|
||||||
|
upx_progress_callback_t *cb,
|
||||||
|
int method, int level,
|
||||||
|
const struct upx_compress_config_t *conf_parm,
|
||||||
|
upx_uintp result )
|
||||||
|
{
|
||||||
|
struct upx_compress_config_t conf;
|
||||||
|
upx_uint result_buffer[16];
|
||||||
|
int r = UPX_E_ERROR;
|
||||||
|
|
||||||
|
assert(level > 0);
|
||||||
|
memset(&conf, 0xff, sizeof(conf));
|
||||||
|
if (conf_parm)
|
||||||
|
conf = *conf_parm; // struct copy
|
||||||
|
if (!result)
|
||||||
|
result = result_buffer;
|
||||||
|
|
||||||
|
// assume no info available - fill in worst case results
|
||||||
|
//result[0] = 1; // min_offset_found - NOT USED
|
||||||
|
result[1] = src_len - 1; // max_offset_found
|
||||||
|
//result[2] = 2; // min_match_found - NOT USED
|
||||||
|
result[3] = src_len - 1; // max_match_found
|
||||||
|
//result[4] = 1; // min_run_found - NOT USED
|
||||||
|
result[5] = src_len; // max_run_found
|
||||||
|
result[6] = 1; // first_offset_found
|
||||||
|
//result[7] = 999999; // same_match_offsets_found - NOT USED
|
||||||
|
|
||||||
|
// prepare bit-buffer settings
|
||||||
|
conf.bb_endian = 0;
|
||||||
|
conf.bb_size = 0;
|
||||||
|
if (method >= M_NRV2B_LE32 && method <= M_NRV2E_LE16)
|
||||||
|
{
|
||||||
|
int n = (method - M_NRV2B_LE32) % 3;
|
||||||
|
if (n == 0)
|
||||||
|
conf.bb_size = 32;
|
||||||
|
else if (n == 1)
|
||||||
|
conf.bb_size = 8;
|
||||||
|
else
|
||||||
|
conf.bb_size = 16;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throwInternalError("unknown compression method");
|
||||||
|
|
||||||
|
// optimize compression parms
|
||||||
|
if (level <= 3 && conf.max_offset == UPX_UINT_MAX)
|
||||||
|
conf.max_offset = 8*1024-1;
|
||||||
|
else if (level == 4 && conf.max_offset == UPX_UINT_MAX)
|
||||||
|
conf.max_offset = 32*1024-1;
|
||||||
|
|
||||||
|
if M_IS_NRV2B(method)
|
||||||
|
r = ucl_nrv2b_99_compress(src, src_len, dst, dst_len,
|
||||||
|
cb, level, &conf, result);
|
||||||
|
else if M_IS_NRV2D(method)
|
||||||
|
r = ucl_nrv2d_99_compress(src, src_len, dst, dst_len,
|
||||||
|
cb, level, &conf, result);
|
||||||
|
#if defined(ALG_NRV2E)
|
||||||
|
else if M_IS_NRV2E(method)
|
||||||
|
r = ucl_nrv2e_99_compress(src, src_len, dst, dst_len,
|
||||||
|
cb, level, &conf, result);
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
throwInternalError("unknown compression method");
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* upx_compress */
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#if defined(upx_decompress)
|
||||||
|
|
||||||
|
int upx_decompress ( const upx_bytep src, upx_uint src_len,
|
||||||
|
upx_bytep dst, upx_uintp dst_len,
|
||||||
|
int method )
|
||||||
|
{
|
||||||
|
int r = UPX_E_ERROR;
|
||||||
|
|
||||||
|
switch (method)
|
||||||
|
{
|
||||||
|
case M_NRV2B_8:
|
||||||
|
r = ucl_nrv2b_decompress_safe_8(src,src_len,dst,dst_len,NULL);
|
||||||
|
break;
|
||||||
|
case M_NRV2B_LE16:
|
||||||
|
r = ucl_nrv2b_decompress_safe_le16(src,src_len,dst,dst_len,NULL);
|
||||||
|
break;
|
||||||
|
case M_NRV2B_LE32:
|
||||||
|
r = ucl_nrv2b_decompress_safe_le32(src,src_len,dst,dst_len,NULL);
|
||||||
|
break;
|
||||||
|
case M_NRV2D_8:
|
||||||
|
r = ucl_nrv2d_decompress_safe_8(src,src_len,dst,dst_len,NULL);
|
||||||
|
break;
|
||||||
|
case M_NRV2D_LE16:
|
||||||
|
r = ucl_nrv2d_decompress_safe_le16(src,src_len,dst,dst_len,NULL);
|
||||||
|
break;
|
||||||
|
case M_NRV2D_LE32:
|
||||||
|
r = ucl_nrv2d_decompress_safe_le32(src,src_len,dst,dst_len,NULL);
|
||||||
|
break;
|
||||||
|
#if defined(ALG_NRV2E)
|
||||||
|
case M_NRV2E_8:
|
||||||
|
r = ucl_nrv2e_decompress_safe_8(src,src_len,dst,dst_len,NULL);
|
||||||
|
break;
|
||||||
|
case M_NRV2E_LE16:
|
||||||
|
r = ucl_nrv2e_decompress_safe_le16(src,src_len,dst,dst_len,NULL);
|
||||||
|
break;
|
||||||
|
case M_NRV2E_LE32:
|
||||||
|
r = ucl_nrv2e_decompress_safe_le32(src,src_len,dst,dst_len,NULL);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
throwInternalError("unknown decompression method");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* upx_decompress */
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#if defined(upx_test_overlap)
|
||||||
|
|
||||||
|
int upx_test_overlap ( const upx_bytep buf, upx_uint src_off,
|
||||||
|
upx_uint src_len, upx_uintp dst_len,
|
||||||
|
int method )
|
||||||
|
{
|
||||||
|
int r = UPX_E_ERROR;
|
||||||
|
|
||||||
|
switch (method)
|
||||||
|
{
|
||||||
|
case M_NRV2B_8:
|
||||||
|
r = ucl_nrv2b_test_overlap_8(buf,src_off,src_len,dst_len,NULL);
|
||||||
|
break;
|
||||||
|
case M_NRV2B_LE16:
|
||||||
|
r = ucl_nrv2b_test_overlap_le16(buf,src_off,src_len,dst_len,NULL);
|
||||||
|
break;
|
||||||
|
case M_NRV2B_LE32:
|
||||||
|
r = ucl_nrv2b_test_overlap_le32(buf,src_off,src_len,dst_len,NULL);
|
||||||
|
break;
|
||||||
|
case M_NRV2D_8:
|
||||||
|
r = ucl_nrv2d_test_overlap_8(buf,src_off,src_len,dst_len,NULL);
|
||||||
|
break;
|
||||||
|
case M_NRV2D_LE16:
|
||||||
|
r = ucl_nrv2d_test_overlap_le16(buf,src_off,src_len,dst_len,NULL);
|
||||||
|
break;
|
||||||
|
case M_NRV2D_LE32:
|
||||||
|
r = ucl_nrv2d_test_overlap_le32(buf,src_off,src_len,dst_len,NULL);
|
||||||
|
break;
|
||||||
|
#if defined(ALG_NRV2E)
|
||||||
|
case M_NRV2E_8:
|
||||||
|
r = ucl_nrv2e_test_overlap_8(buf,src_off,src_len,dst_len,NULL);
|
||||||
|
break;
|
||||||
|
case M_NRV2E_LE16:
|
||||||
|
r = ucl_nrv2e_test_overlap_le16(buf,src_off,src_len,dst_len,NULL);
|
||||||
|
break;
|
||||||
|
case M_NRV2E_LE32:
|
||||||
|
r = ucl_nrv2e_test_overlap_le32(buf,src_off,src_len,dst_len,NULL);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
throwInternalError("unknown decompression method");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* upx_test_overlap */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
vi:ts=4:et:nowrap
|
||||||
|
*/
|
||||||
|
|
||||||
+16
-234
@@ -1,9 +1,9 @@
|
|||||||
/* compress.cpp -- interface to the compression library
|
/* compress.cpp --
|
||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,246 +22,28 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
|
||||||
#if defined(WITH_UCL) && !defined(WITH_NRV)
|
|
||||||
# define nrv2b_99_compress_internal ucl_nrv2b_99_compress
|
|
||||||
# define nrv2d_99_compress_internal ucl_nrv2d_99_compress
|
|
||||||
# if 0 && defined(__i386__)
|
|
||||||
# include <ucl/ucl_asm.h>
|
|
||||||
# define nrv2b_decompress_safe_8 ucl_nrv2b_decompress_asm_safe_8
|
|
||||||
# define nrv2b_decompress_safe_le16 ucl_nrv2b_decompress_asm_safe_le16
|
|
||||||
# define nrv2b_decompress_safe_le32 ucl_nrv2b_decompress_asm_safe_le32
|
|
||||||
# define nrv2d_decompress_safe_8 ucl_nrv2d_decompress_asm_safe_8
|
|
||||||
# define nrv2d_decompress_safe_le16 ucl_nrv2d_decompress_asm_safe_le16
|
|
||||||
# define nrv2d_decompress_safe_le32 ucl_nrv2d_decompress_asm_safe_le32
|
|
||||||
# else
|
|
||||||
# define nrv2b_decompress_safe_8 ucl_nrv2b_decompress_safe_8
|
|
||||||
# define nrv2b_decompress_safe_le16 ucl_nrv2b_decompress_safe_le16
|
|
||||||
# define nrv2b_decompress_safe_le32 ucl_nrv2b_decompress_safe_le32
|
|
||||||
# define nrv2d_decompress_safe_8 ucl_nrv2d_decompress_safe_8
|
|
||||||
# define nrv2d_decompress_safe_le16 ucl_nrv2d_decompress_safe_le16
|
|
||||||
# define nrv2d_decompress_safe_le32 ucl_nrv2d_decompress_safe_le32
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(WITH_NRV)
|
#if defined(WITH_NRV)
|
||||||
# include <nrv/nrv2b.h>
|
# include "compress_nrv.ch"
|
||||||
# include <nrv/nrv2d.h>
|
#elif defined(WITH_UCL)
|
||||||
# if !defined(NRV_VERSION) || (NRV_VERSION < 0x007300L)
|
# define upx_adler32 upx_adler32
|
||||||
|
//# define upx_crc32 upx_crc32
|
||||||
|
# define upx_compress upx_compress
|
||||||
|
# define upx_decompress upx_decompress
|
||||||
|
# if (UPX_VERSION_HEX >= 0x019000)
|
||||||
|
# define ALG_NRV2E
|
||||||
|
# define upx_test_overlap upx_test_overlap
|
||||||
|
# endif
|
||||||
|
# include "compress.ch"
|
||||||
|
#else
|
||||||
# error
|
# error
|
||||||
#endif
|
#endif
|
||||||
# if 1 && defined(__i386__)
|
|
||||||
# define nrv2b_decompress_safe_8 nrv2b_decompress_asm_safe_8
|
|
||||||
# define nrv2b_decompress_safe_le16 nrv2b_decompress_asm_safe_le16
|
|
||||||
# define nrv2d_decompress_safe_8 nrv2d_decompress_asm_safe_8
|
|
||||||
# define nrv2d_decompress_safe_le16 nrv2d_decompress_asm_safe_le16
|
|
||||||
# if (NRV_VERSION < 0x008000L)
|
|
||||||
# define nrv2b_decompress_safe_le32 nrv2b_decompress_asm_safe
|
|
||||||
# define nrv2d_decompress_safe_le32 nrv2d_decompress_asm_safe
|
|
||||||
# else
|
|
||||||
# define nrv2b_decompress_safe_le32 nrv2b_decompress_asm_safe_le32
|
|
||||||
# define nrv2d_decompress_safe_le32 nrv2d_decompress_asm_safe_le32
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
NRV_EXTERN_CDECL(int) nrv2b_99_compress_internal(...);
|
|
||||||
NRV_EXTERN_CDECL(int) nrv2d_99_compress_internal(...);
|
|
||||||
NRV_EXTERN_CDECL(int) nrv2b_decompress_safe_8(...);
|
|
||||||
NRV_EXTERN_CDECL(int) nrv2b_decompress_safe_le16(...);
|
|
||||||
NRV_EXTERN_CDECL(int) nrv2b_decompress_safe_le32(...);
|
|
||||||
NRV_EXTERN_CDECL(int) nrv2d_decompress_safe_8(...);
|
|
||||||
NRV_EXTERN_CDECL(int) nrv2d_decompress_safe_le16(...);
|
|
||||||
NRV_EXTERN_CDECL(int) nrv2d_decompress_safe_le32(...);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0 && defined(WITH_ZLIB) && defined(M_ZLIB)
|
|
||||||
# include <zlib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
//
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
int upx_compress ( const upx_byte *src, upx_uint src_len,
|
|
||||||
upx_byte *dst, upx_uint *dst_len,
|
|
||||||
upx_progress_callback_t *cb,
|
|
||||||
int method, int level,
|
|
||||||
const struct upx_compress_config_t *conf_parm,
|
|
||||||
upx_uintp result)
|
|
||||||
{
|
|
||||||
struct upx_compress_config_t conf;
|
|
||||||
upx_uint result_buffer[16];
|
|
||||||
int r = UPX_E_ERROR;
|
|
||||||
|
|
||||||
assert(level > 0);
|
|
||||||
memset(&conf, 0xff, sizeof(conf));
|
|
||||||
if (conf_parm)
|
|
||||||
conf = *conf_parm; // struct copy
|
|
||||||
if (!result)
|
|
||||||
result = result_buffer;
|
|
||||||
|
|
||||||
// assume no info available - fill in worst case results
|
|
||||||
//result[0] = 1; // min_offset_found - NOT USED
|
|
||||||
result[1] = src_len - 1; // max_offset_found
|
|
||||||
//result[2] = 2; // min_match_found - NOT USED
|
|
||||||
result[3] = src_len - 1; // max_match_found
|
|
||||||
//result[4] = 1; // min_run_found - NOT USED
|
|
||||||
result[5] = src_len; // max_run_found
|
|
||||||
result[6] = 1; // first_offset_found
|
|
||||||
//result[7] = 999999; // same_match_offsets_found - NOT USED
|
|
||||||
|
|
||||||
#if 0 && defined(WITH_ZLIB) && defined(M_ZLIB)
|
|
||||||
if (method == M_ZLIB)
|
|
||||||
{
|
|
||||||
uLong destLen = src_len + src_len / 8 + 256;
|
|
||||||
r = compress2(dst, &destLen, src, src_len, UPX_MIN(level, 9));
|
|
||||||
*dst_len = destLen;
|
|
||||||
if (r == Z_MEM_ERROR)
|
|
||||||
return UPX_E_OUT_OF_MEMORY;
|
|
||||||
if (r != Z_OK)
|
|
||||||
return UPX_E_ERROR;
|
|
||||||
return UPX_E_OK;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// prepare bit-buffer settings
|
|
||||||
conf.bb_endian = 0;
|
|
||||||
conf.bb_size = 0;
|
|
||||||
if (method == M_NRV2B_LE32 || method == M_NRV2D_LE32)
|
|
||||||
conf.bb_size = 32;
|
|
||||||
else if (method == M_NRV2B_8 || method == M_NRV2D_8)
|
|
||||||
conf.bb_size = 8;
|
|
||||||
else if (method == M_NRV2B_LE16 || method == M_NRV2D_LE16)
|
|
||||||
conf.bb_size = 16;
|
|
||||||
else
|
|
||||||
throwInternalError("unknown compression method");
|
|
||||||
|
|
||||||
#if 1 && defined(WITH_NRV)
|
|
||||||
if (level == 1 && conf.bb_size == 32 &&
|
|
||||||
conf.max_offset == UPX_UINT_MAX && conf.max_match == UPX_UINT_MAX)
|
|
||||||
{
|
|
||||||
if (method == M_NRV2B_LE32)
|
|
||||||
{
|
|
||||||
upx_byte wrkmem[NRV2B_1_16_MEM_COMPRESS];
|
|
||||||
#if defined(__UPX_CHECKER)
|
|
||||||
memset(wrkmem,0,NRV2B_1_16_MEM_COMPRESS);
|
|
||||||
#endif
|
|
||||||
r = nrv2b_1_16_compress(src, src_len, dst, dst_len, wrkmem);
|
|
||||||
}
|
|
||||||
else if (method == M_NRV2D_LE32)
|
|
||||||
{
|
|
||||||
upx_byte wrkmem[NRV2D_1_16_MEM_COMPRESS];
|
|
||||||
#if defined(__UPX_CHECKER)
|
|
||||||
memset(wrkmem,0,NRV2D_1_16_MEM_COMPRESS);
|
|
||||||
#endif
|
|
||||||
r = nrv2d_1_16_compress(src, src_len, dst, dst_len, wrkmem);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
throwInternalError("unknown compression method");
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// optimize compression parms
|
|
||||||
if (level <= 3 && conf.max_offset == UPX_UINT_MAX)
|
|
||||||
conf.max_offset = 8*1024-1;
|
|
||||||
else if (level == 4 && conf.max_offset == UPX_UINT_MAX)
|
|
||||||
conf.max_offset = 32*1024-1;
|
|
||||||
#if defined(WITH_NRV)
|
|
||||||
else if (level <= 7 && conf.max_offset == UPX_UINT_MAX)
|
|
||||||
conf.max_offset = 1024*1024-1;
|
|
||||||
else if (level <= 8 && conf.max_offset == UPX_UINT_MAX)
|
|
||||||
conf.max_offset = 2048*1024-1;
|
|
||||||
else if (level <= 10 && conf.max_offset == UPX_UINT_MAX)
|
|
||||||
conf.max_offset = 4096*1024-1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if M_IS_NRV2B(method)
|
|
||||||
r = nrv2b_99_compress_internal(src, src_len, dst, dst_len,
|
|
||||||
cb, level, &conf, result);
|
|
||||||
else if M_IS_NRV2D(method)
|
|
||||||
r = nrv2d_99_compress_internal(src, src_len, dst, dst_len,
|
|
||||||
cb, level, &conf, result);
|
|
||||||
else
|
|
||||||
throwInternalError("unknown compression method");
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
//
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
int upx_decompress ( const upx_byte *src, upx_uint src_len,
|
|
||||||
upx_byte *dst, upx_uint *dst_len,
|
|
||||||
int method )
|
|
||||||
{
|
|
||||||
int r = UPX_E_ERROR;
|
|
||||||
|
|
||||||
#if 0 && defined(WITH_ZLIB) && defined(M_ZLIB)
|
|
||||||
if (method == M_ZLIB)
|
|
||||||
{
|
|
||||||
uLong destLen = *dst_len;
|
|
||||||
r = uncompress(dst, &destLen, src, src_len);
|
|
||||||
*dst_len = destLen;
|
|
||||||
if (r == Z_MEM_ERROR)
|
|
||||||
return UPX_E_OUT_OF_MEMORY;
|
|
||||||
if (r != Z_OK)
|
|
||||||
return UPX_E_ERROR;
|
|
||||||
return UPX_E_OK;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (method == M_NRV2B_LE32)
|
|
||||||
r = nrv2b_decompress_safe_le32(src,src_len,dst,dst_len,NULL);
|
|
||||||
else if (method == M_NRV2B_8)
|
|
||||||
r = nrv2b_decompress_safe_8(src,src_len,dst,dst_len,NULL);
|
|
||||||
else if (method == M_NRV2B_LE16)
|
|
||||||
r = nrv2b_decompress_safe_le16(src,src_len,dst,dst_len,NULL);
|
|
||||||
else if (method == M_NRV2D_LE32)
|
|
||||||
r = nrv2d_decompress_safe_le32(src,src_len,dst,dst_len,NULL);
|
|
||||||
else if (method == M_NRV2D_8)
|
|
||||||
r = nrv2d_decompress_safe_8(src,src_len,dst,dst_len,NULL);
|
|
||||||
else if (method == M_NRV2D_LE16)
|
|
||||||
r = nrv2d_decompress_safe_le16(src,src_len,dst,dst_len,NULL);
|
|
||||||
else
|
|
||||||
throwInternalError("unknown decompression method");
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
//
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
int upx_test_overlap ( const upx_byte *buf, upx_uint src_off,
|
|
||||||
upx_uint src_len, upx_uint *dst_len,
|
|
||||||
int method )
|
|
||||||
{
|
|
||||||
int r = UPX_E_ERROR;
|
|
||||||
|
|
||||||
if (method == M_NRV2B_LE32)
|
|
||||||
r = ucl_nrv2b_test_overlap_le32(buf,src_off,src_len,dst_len,NULL);
|
|
||||||
else if (method == M_NRV2B_8)
|
|
||||||
r = ucl_nrv2b_test_overlap_8(buf,src_off,src_len,dst_len,NULL);
|
|
||||||
else if (method == M_NRV2B_LE16)
|
|
||||||
r = ucl_nrv2b_test_overlap_le16(buf,src_off,src_len,dst_len,NULL);
|
|
||||||
else if (method == M_NRV2D_LE32)
|
|
||||||
r = ucl_nrv2d_test_overlap_le32(buf,src_off,src_len,dst_len,NULL);
|
|
||||||
else if (method == M_NRV2D_8)
|
|
||||||
r = ucl_nrv2d_test_overlap_8(buf,src_off,src_len,dst_len,NULL);
|
|
||||||
else if (method == M_NRV2D_LE16)
|
|
||||||
r = ucl_nrv2d_test_overlap_le16(buf,src_off,src_len,dst_len,NULL);
|
|
||||||
else
|
|
||||||
throwInternalError("unknown decompression method");
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
+170
-177
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -36,11 +36,39 @@
|
|||||||
#if defined(UPX_CONFIG_H)
|
#if defined(UPX_CONFIG_H)
|
||||||
# include UPX_CONFIG_H
|
# include UPX_CONFIG_H
|
||||||
#endif
|
#endif
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
|
#if defined(HAVE_STDINT_H)
|
||||||
|
# if !defined(__STDC_LIMIT_MACROS)
|
||||||
|
# define __STDC_LIMIT_MACROS 1
|
||||||
|
# endif
|
||||||
|
# if !defined(__STDC_CONSTANT_MACROS)
|
||||||
|
# define __STDC_CONSTANT_MACROS 1
|
||||||
|
# endif
|
||||||
|
# include <stdint.h>
|
||||||
|
#endif
|
||||||
|
#include <limits.h>
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "tailor.h"
|
#include "tailor.h"
|
||||||
|
|
||||||
|
// upx_int64l is int_least64_t in <stdint.h> terminology
|
||||||
|
#if !defined(upx_int64l)
|
||||||
|
# if defined(HAVE_STDINT_H)
|
||||||
|
# define upx_int64l int_least64_t
|
||||||
|
# define upx_uint64l uint_least64_t
|
||||||
|
# elif (ULONG_MAX > 0xffffffffL)
|
||||||
|
# define upx_int64l long int
|
||||||
|
# define upx_uint64l unsigned long int
|
||||||
|
# elif defined(__GNUC__) || defined(__DMC__)
|
||||||
|
# define upx_int64l long long int
|
||||||
|
# define upx_uint64l unsigned long long int
|
||||||
|
# elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__WATCOMC__)
|
||||||
|
# define upx_int64l __int64
|
||||||
|
# define upx_uint64l unsigned __int64
|
||||||
|
# else
|
||||||
|
# error "need a 64-bit integer type"
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(__i386__)
|
#if !defined(__i386__)
|
||||||
# if defined(__386__) || defined(_M_IX86)
|
# if defined(__386__) || defined(_M_IX86)
|
||||||
# define __i386__ 1
|
# define __i386__ 1
|
||||||
@@ -59,9 +87,15 @@
|
|||||||
#undef unix
|
#undef unix
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(WITH_UCL)
|
||||||
|
# error "you lose"
|
||||||
|
#endif
|
||||||
#if defined(WITH_UCL)
|
#if defined(WITH_UCL)
|
||||||
# include <ucl/uclconf.h>
|
# include <ucl/uclconf.h>
|
||||||
# include <ucl/ucl.h>
|
# include <ucl/ucl.h>
|
||||||
|
# if !defined(UCL_VERSION) || (UCL_VERSION < 0x010100L)
|
||||||
|
# error "please upgrade your UCL installation"
|
||||||
|
# endif
|
||||||
# if !defined(UPX_UINT_MAX)
|
# if !defined(UPX_UINT_MAX)
|
||||||
# define UPX_UINT_MAX UCL_UINT_MAX
|
# define UPX_UINT_MAX UCL_UINT_MAX
|
||||||
# define upx_uint ucl_uint
|
# define upx_uint ucl_uint
|
||||||
@@ -70,8 +104,8 @@
|
|||||||
# define upx_byte ucl_byte
|
# define upx_byte ucl_byte
|
||||||
# define upx_bytep ucl_bytep
|
# define upx_bytep ucl_bytep
|
||||||
# define upx_bool ucl_bool
|
# define upx_bool ucl_bool
|
||||||
|
# define upx_compress_config_t ucl_compress_config_t
|
||||||
# define upx_progress_callback_t ucl_progress_callback_t
|
# define upx_progress_callback_t ucl_progress_callback_t
|
||||||
# define upx_adler32 ucl_adler32
|
|
||||||
# define UPX_E_OK UCL_E_OK
|
# define UPX_E_OK UCL_E_OK
|
||||||
# define UPX_E_ERROR UCL_E_ERROR
|
# define UPX_E_ERROR UCL_E_ERROR
|
||||||
# define UPX_E_OUT_OF_MEMORY UCL_E_OUT_OF_MEMORY
|
# define UPX_E_OUT_OF_MEMORY UCL_E_OUT_OF_MEMORY
|
||||||
@@ -80,40 +114,15 @@
|
|||||||
#endif
|
#endif
|
||||||
#if defined(WITH_NRV)
|
#if defined(WITH_NRV)
|
||||||
# include <nrv/nrvconf.h>
|
# include <nrv/nrvconf.h>
|
||||||
# if !defined(UPX_UINT_MAX)
|
|
||||||
# define UPX_UINT_MAX NRV_UINT_MAX
|
|
||||||
# define upx_uint nrv_uint
|
|
||||||
# define upx_voidp nrv_voidp
|
|
||||||
# define upx_uintp nrv_uintp
|
|
||||||
# define upx_byte nrv_byte
|
|
||||||
# define upx_bytep nrv_bytep
|
|
||||||
# define upx_bool nrv_bool
|
|
||||||
# define upx_progress_callback_t nrv_progress_callback_t
|
|
||||||
# define upx_adler32 nrv_adler32
|
|
||||||
# define UPX_E_OK NRV_E_OK
|
|
||||||
# define UPX_E_ERROR NRV_E_ERROR
|
|
||||||
# define UPX_E_OUT_OF_MEMORY NRV_E_OUT_OF_MEMORY
|
|
||||||
# define __UPX_ENTRY __NRV_ENTRY
|
|
||||||
# endif
|
|
||||||
#endif
|
#endif
|
||||||
#if !defined(__UPX_CHECKER)
|
#if !defined(__UPX_CHECKER)
|
||||||
# if defined(__UCL_CHECKER) || defined(__NRV_CHECKER)
|
# if defined(__UCL_CHECKER) || defined(__NRV_CHECKER)
|
||||||
# define __UPX_CHECKER
|
# define __UPX_CHECKER
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
#if !defined(UPX_UINT_MAX) || (UINT_MAX < 0xffffffffL)
|
#if !defined(UINT_MAX) || (UINT_MAX < 0xffffffffL)
|
||||||
# error "you lose"
|
# error "you lose"
|
||||||
#endif
|
#endif
|
||||||
#if !defined(WITH_UCL)
|
|
||||||
# error "you lose"
|
|
||||||
#endif
|
|
||||||
#if !defined(UCL_VERSION) || (UCL_VERSION < 0x009200L)
|
|
||||||
# error "please upgrade your UCL installation"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef WITH_ZLIB
|
|
||||||
# define WITH_ZLIB 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
@@ -177,7 +186,9 @@
|
|||||||
|
|
||||||
|
|
||||||
// malloc debuggers
|
// malloc debuggers
|
||||||
#if defined(WITH_DMALLOC)
|
#if defined(WITH_VALGRIND)
|
||||||
|
# include <valgrind.h>
|
||||||
|
#elif defined(WITH_DMALLOC)
|
||||||
# define DMALLOC_FUNC_CHECK
|
# define DMALLOC_FUNC_CHECK
|
||||||
# include <dmalloc.h>
|
# include <dmalloc.h>
|
||||||
#elif defined(WITH_GC)
|
#elif defined(WITH_GC)
|
||||||
@@ -189,9 +200,20 @@
|
|||||||
# define malloc GC_MALLOC
|
# define malloc GC_MALLOC
|
||||||
# define realloc GC_REALLOC
|
# define realloc GC_REALLOC
|
||||||
# define free GC_FREE
|
# define free GC_FREE
|
||||||
#elif defined(WITH_MSS)
|
#endif
|
||||||
# define MSS
|
|
||||||
# include <mss.h>
|
#if !defined(VALGRIND_MAKE_WRITABLE)
|
||||||
|
# define VALGRIND_MAKE_WRITABLE(addr,len) 0
|
||||||
|
#endif
|
||||||
|
#if !defined(VALGRIND_MAKE_READABLE)
|
||||||
|
# if 0
|
||||||
|
# define VALGRIND_MAKE_READABLE(addr,len) memset(addr,0,len), 0
|
||||||
|
# else
|
||||||
|
# define VALGRIND_MAKE_READABLE(addr,len) 0
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#if !defined(VALGRIND_DISCARD)
|
||||||
|
# define VALGRIND_DISCARD(handle) ((void) &handle)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -199,10 +221,17 @@
|
|||||||
// portab
|
// portab
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#if defined(NO_BOOL)
|
#if defined(__GNUC__) && !defined(__GNUC_VERSION_HEX__)
|
||||||
typedef int bool;
|
# if !defined(__GNUC_MINOR__)
|
||||||
enum { false, true };
|
# error
|
||||||
# endif
|
# endif
|
||||||
|
# if !defined(__GNUC_PATCHLEVEL__)
|
||||||
|
# define __GNUC_PATCHLEVEL__ 0
|
||||||
|
# endif
|
||||||
|
# define __GNUC_VERSION_HEX__ \
|
||||||
|
(__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if !defined(PATH_MAX)
|
#if !defined(PATH_MAX)
|
||||||
# define PATH_MAX 512
|
# define PATH_MAX 512
|
||||||
@@ -220,6 +249,7 @@ enum { false, true };
|
|||||||
#endif
|
#endif
|
||||||
typedef RETSIGTYPE (SIGTYPEENTRY *sig_type)(int);
|
typedef RETSIGTYPE (SIGTYPEENTRY *sig_type)(int);
|
||||||
|
|
||||||
|
|
||||||
#undef MODE_T
|
#undef MODE_T
|
||||||
#if defined(HAVE_MODE_T)
|
#if defined(HAVE_MODE_T)
|
||||||
# define MODE_T mode_t
|
# define MODE_T mode_t
|
||||||
@@ -227,6 +257,7 @@ typedef RETSIGTYPE (SIGTYPEENTRY *sig_type)(int);
|
|||||||
# define MODE_T int
|
# define MODE_T int
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if !defined(HAVE_STRCASECMP)
|
#if !defined(HAVE_STRCASECMP)
|
||||||
# if defined(HAVE_STRICMP)
|
# if defined(HAVE_STRICMP)
|
||||||
# define strcasecmp stricmp
|
# define strcasecmp stricmp
|
||||||
@@ -299,8 +330,43 @@ typedef RETSIGTYPE (SIGTYPEENTRY *sig_type)(int);
|
|||||||
#define index upx_index
|
#define index upx_index
|
||||||
#define outp upx_outp
|
#define outp upx_outp
|
||||||
|
|
||||||
// a dummy statement
|
|
||||||
#define nop ((void)0)
|
#if 0
|
||||||
|
# define COMPILE_TIME_ASSERT(expr) \
|
||||||
|
{ typedef char __upx_compile_time_assert_fail[1 - 2 * !(expr)]; \
|
||||||
|
switch (sizeof(__upx_compile_time_assert_fail)) { \
|
||||||
|
case 1: case !(expr): break; \
|
||||||
|
} }
|
||||||
|
#elif defined(__SC__)
|
||||||
|
# define COMPILE_TIME_ASSERT(expr) \
|
||||||
|
{ switch (1) { case 1: case !(expr): break; } }
|
||||||
|
#elif 0
|
||||||
|
# define COMPILE_TIME_ASSERT(expr) \
|
||||||
|
{ typedef int __upx_compile_time_assert_fail[1 - 2 * !(expr)]; typedef int a[sizeof(__upx_compile_time_assert_fail]; }
|
||||||
|
#else
|
||||||
|
# define COMPILE_TIME_ASSERT(expr) \
|
||||||
|
{ typedef int __upx_compile_time_assert_fail[1 - 2 * !(expr)]; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#undef __attribute_packed
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
# if 1 && defined(__i386__)
|
||||||
|
# define __attribute_packed
|
||||||
|
# else
|
||||||
|
# define __attribute_packed __attribute__((__packed__,__aligned__(1)))
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define __attribute_packed
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#undef NOTHROW
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
# define NOTHROW throw()
|
||||||
|
#else
|
||||||
|
# define NOTHROW
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
@@ -318,6 +384,10 @@ typedef RETSIGTYPE (SIGTYPEENTRY *sig_type)(int);
|
|||||||
# define O_BINARY 0
|
# define O_BINARY 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__DMC__)
|
||||||
|
# undef tell
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__DJGPP__)
|
#if defined(__DJGPP__)
|
||||||
# undef sopen
|
# undef sopen
|
||||||
# undef USE_SETMODE
|
# undef USE_SETMODE
|
||||||
@@ -328,11 +398,14 @@ typedef RETSIGTYPE (SIGTYPEENTRY *sig_type)(int);
|
|||||||
// memory util
|
// memory util
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#undef FREE
|
|
||||||
#define FREE(ptr) if (ptr) { free(ptr); ptr = NULL; }
|
|
||||||
|
|
||||||
#undef UNUSED
|
#undef UNUSED
|
||||||
#if defined(__BORLANDC__)
|
#if 1
|
||||||
|
# define UNUSED(var) ((void) &(var))
|
||||||
|
#elif 1 && defined(__GNUC__)
|
||||||
|
# define UNUSED(var) { typedef int __upx_unused[sizeof(var) ? 1 : -1]; }
|
||||||
|
#elif 0
|
||||||
|
# define UNUSED(var) do { } while (!sizeof(var))
|
||||||
|
#elif defined(__BORLANDC__)
|
||||||
# define UNUSED(parm) ((void)(parm))
|
# define UNUSED(parm) ((void)(parm))
|
||||||
#else
|
#else
|
||||||
# define UNUSED(parm) (parm = parm)
|
# define UNUSED(parm) (parm = parm)
|
||||||
@@ -349,7 +422,7 @@ typedef RETSIGTYPE (SIGTYPEENTRY *sig_type)(int);
|
|||||||
#define UPX_MIN3(a,b,c) ((a) <= (b) ? UPX_MIN(a,c) : UPX_MIN(b,c))
|
#define UPX_MIN3(a,b,c) ((a) <= (b) ? UPX_MIN(a,c) : UPX_MIN(b,c))
|
||||||
|
|
||||||
|
|
||||||
#if 0 && defined(__cplusplus)
|
#if 0 && defined(__cplusplus) && !defined(new) && !defined(delete)
|
||||||
// global operators - debug
|
// global operators - debug
|
||||||
inline void *operator new(size_t l)
|
inline void *operator new(size_t l)
|
||||||
{
|
{
|
||||||
@@ -361,7 +434,7 @@ inline void *operator new(size_t l)
|
|||||||
inline void *operator new[](size_t l)
|
inline void *operator new[](size_t l)
|
||||||
{
|
{
|
||||||
void *p = malloc(l);
|
void *p = malloc(l);
|
||||||
printf("new %6ld %p\n",(long)l,p);
|
printf("new[] %6ld %p\n",(long)l,p);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -373,32 +446,27 @@ inline void operator delete(void *p)
|
|||||||
}
|
}
|
||||||
inline void operator delete[](void *p)
|
inline void operator delete[](void *p)
|
||||||
{
|
{
|
||||||
printf("delete %p\n",p);
|
printf("delete[] %p\n",p);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
if (p) free(p);
|
if (p) free(p);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// A autoheap_array allocates memory on the heap, but automatically
|
// An Array allocates memory on the heap, but automatically
|
||||||
// gets destructed when leaving scope or on exceptions.
|
// gets destructed when leaving scope or on exceptions.
|
||||||
// "var" is declared as a read-only reference to a pointer
|
// "var" is declared as a read-only reference to a pointer
|
||||||
// and behaves exactly like an array "var[]".
|
// and behaves exactly like an array "var[]".
|
||||||
#if 0
|
#define Array(type, var, size) \
|
||||||
# define autoheap_array(type, var, size) \
|
|
||||||
assert((int)(size) > 0); \
|
assert((int)(size) > 0); \
|
||||||
vector<type> var ## _autoheap_vec((size)); \
|
MemBuffer var ## _membuf((size)*(sizeof(type))); \
|
||||||
type * const & var = & var ## _autoheap_vec[0]
|
type * const & var = ((type *) var ## _membuf.getVoidPtr())
|
||||||
#else
|
|
||||||
# define autoheap_array(type, var, size) \
|
#define ByteArray(var, size) Array(unsigned char, var, size)
|
||||||
assert((int)(size) > 0); \
|
|
||||||
MemBuffer var ## _autoheap_buf((size)*(sizeof(type))); \
|
|
||||||
type * const & var = (type *) (unsigned char *) var ## _autoheap_buf
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
// constants
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
/* exit codes of this program: 0 ok, 1 error, 2 warning */
|
/* exit codes of this program: 0 ok, 1 error, 2 warning */
|
||||||
@@ -422,117 +490,57 @@ inline void operator delete[](void *p)
|
|||||||
#define M_NRV2D_LE32 5
|
#define M_NRV2D_LE32 5
|
||||||
#define M_NRV2D_8 6
|
#define M_NRV2D_8 6
|
||||||
#define M_NRV2D_LE16 7
|
#define M_NRV2D_LE16 7
|
||||||
|
#define M_NRV2E_LE32 8
|
||||||
|
#define M_NRV2E_8 9
|
||||||
|
#define M_NRV2E_LE16 10
|
||||||
|
|
||||||
#define M_IS_NRV2B(x) ((x) >= M_NRV2B_LE32 && (x) <= M_NRV2B_LE16)
|
#define M_IS_NRV2B(x) ((x) >= M_NRV2B_LE32 && (x) <= M_NRV2B_LE16)
|
||||||
#define M_IS_NRV2D(x) ((x) >= M_NRV2D_LE32 && (x) <= M_NRV2D_LE16)
|
#define M_IS_NRV2D(x) ((x) >= M_NRV2D_LE32 && (x) <= M_NRV2D_LE16)
|
||||||
|
#define M_IS_NRV2E(x) ((x) >= M_NRV2E_LE32 && (x) <= M_NRV2E_LE16)
|
||||||
|
|
||||||
|
|
||||||
|
// Executable formats. Note: big endian types are >= 128.
|
||||||
|
#define UPX_F_DOS_COM 1
|
||||||
|
#define UPX_F_DOS_SYS 2
|
||||||
|
#define UPX_F_DOS_EXE 3
|
||||||
|
#define UPX_F_DJGPP2_COFF 4
|
||||||
|
#define UPX_F_WC_LE 5
|
||||||
|
#define UPX_F_VXD_LE 6
|
||||||
|
#define UPX_F_DOS_EXEH 7 /* OBSOLETE */
|
||||||
|
#define UPX_F_TMT_ADAM 8
|
||||||
|
#define UPX_F_WIN32_PE 9
|
||||||
|
#define UPX_F_LINUX_i386 10
|
||||||
|
#define UPX_F_WIN16_NE 11
|
||||||
|
#define UPX_F_LINUX_ELF_i386 12
|
||||||
|
#define UPX_F_LINUX_SEP_i386 13
|
||||||
|
#define UPX_F_LINUX_SH_i386 14
|
||||||
|
#define UPX_F_VMLINUZ_i386 15
|
||||||
|
#define UPX_F_BVMLINUZ_i386 16
|
||||||
|
#define UPX_F_ELKS_8086 17
|
||||||
|
#define UPX_F_PS1_EXE 18
|
||||||
|
#define UPX_F_ATARI_TOS 129
|
||||||
|
#define UPX_F_SOLARIS_SPARC 130
|
||||||
|
|
||||||
|
|
||||||
|
#define UPX_MAGIC_LE32 0x21585055 /* "UPX!" */
|
||||||
|
#define UPX_MAGIC2_LE32 0xD5D0D8A1
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// globals
|
// globals
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include "unupx.h"
|
#include "snprintf.h"
|
||||||
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
|
|
||||||
#include "stdcxx.h"
|
#include "stdcxx.h"
|
||||||
|
#include "options.h"
|
||||||
#include "except.h"
|
#include "except.h"
|
||||||
#include "bele.h"
|
#include "bele.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
|
|
||||||
// options
|
|
||||||
enum {
|
|
||||||
CMD_NONE,
|
|
||||||
CMD_COMPRESS, CMD_DECOMPRESS, CMD_TEST, CMD_LIST, CMD_FILEINFO,
|
|
||||||
CMD_HELP, CMD_LICENSE, CMD_VERSION
|
|
||||||
};
|
|
||||||
|
|
||||||
struct options_t {
|
|
||||||
int cmd;
|
|
||||||
|
|
||||||
// compression options
|
|
||||||
int method;
|
|
||||||
int level; // compression level 1..10
|
|
||||||
int mem_level; // memory level 1..9
|
|
||||||
int filter; // preferred filter from Packer::getFilters()
|
|
||||||
bool all_filters; // try all filters ?
|
|
||||||
|
|
||||||
// other options
|
|
||||||
int backup;
|
|
||||||
int console;
|
|
||||||
int debug;
|
|
||||||
int force;
|
|
||||||
int info_mode;
|
|
||||||
bool ignorewarn;
|
|
||||||
bool no_env;
|
|
||||||
bool no_progress;
|
|
||||||
const char *output_name;
|
|
||||||
int small;
|
|
||||||
int verbose;
|
|
||||||
bool to_stdout;
|
|
||||||
|
|
||||||
// overlay handling
|
|
||||||
enum {
|
|
||||||
SKIP_OVERLAY = 0,
|
|
||||||
COPY_OVERLAY = 1,
|
|
||||||
STRIP_OVERLAY = 2
|
|
||||||
};
|
|
||||||
int overlay;
|
|
||||||
|
|
||||||
// compression runtime parameters - see struct ucl_compress_config_t
|
|
||||||
struct {
|
|
||||||
upx_uint max_offset;
|
|
||||||
upx_uint max_match;
|
|
||||||
int s_level;
|
|
||||||
int h_level;
|
|
||||||
int p_level;
|
|
||||||
int c_flags;
|
|
||||||
upx_uint m_size;
|
|
||||||
} crp;
|
|
||||||
|
|
||||||
// CPU
|
|
||||||
enum {
|
|
||||||
CPU_DEFAULT = 0,
|
|
||||||
CPU_8086 = 1,
|
|
||||||
CPU_286 = 2,
|
|
||||||
CPU_386 = 3,
|
|
||||||
CPU_486 = 4,
|
|
||||||
CPU_586 = 5,
|
|
||||||
CPU_686 = 6
|
|
||||||
};
|
|
||||||
int cpu;
|
|
||||||
|
|
||||||
// options for various executable formats
|
|
||||||
struct {
|
|
||||||
bool force_stub;
|
|
||||||
bool no_reloc;
|
|
||||||
} dos;
|
|
||||||
struct {
|
|
||||||
bool coff;
|
|
||||||
} djgpp2;
|
|
||||||
struct {
|
|
||||||
bool split_segments;
|
|
||||||
} tos;
|
|
||||||
struct {
|
|
||||||
unsigned blocksize;
|
|
||||||
enum { SCRIPT_MAX = 32 };
|
|
||||||
const char *script_name;
|
|
||||||
} unix;
|
|
||||||
struct {
|
|
||||||
bool le;
|
|
||||||
} wcle;
|
|
||||||
struct {
|
|
||||||
int compress_exports;
|
|
||||||
int compress_icons;
|
|
||||||
bool compress_resources;
|
|
||||||
int strip_relocs;
|
|
||||||
} w32pe;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct options_t * volatile opt;
|
|
||||||
|
|
||||||
|
|
||||||
// main.cpp
|
// main.cpp
|
||||||
extern const char *progname;
|
extern const char *progname;
|
||||||
@@ -549,7 +557,7 @@ void e_exit(int ec);
|
|||||||
void printSetNl(int need_nl);
|
void printSetNl(int need_nl);
|
||||||
void printClearLine(FILE *f = NULL);
|
void printClearLine(FILE *f = NULL);
|
||||||
void printErr(const char *iname, const Throwable *e);
|
void printErr(const char *iname, const Throwable *e);
|
||||||
void printUnhandledException(const char *iname, const exception *e);
|
void printUnhandledException(const char *iname, const std::exception *e);
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
void printErr(const char *iname, const char *format, ...)
|
void printErr(const char *iname, const char *format, ...)
|
||||||
__attribute__((format(printf,2,3)));
|
__attribute__((format(printf,2,3)));
|
||||||
@@ -590,38 +598,23 @@ void show_version(int);
|
|||||||
|
|
||||||
|
|
||||||
// compress.cpp
|
// compress.cpp
|
||||||
#if defined(WITH_UCL)
|
unsigned upx_adler32(const void *buf, unsigned len, unsigned adler=1);
|
||||||
#define upx_compress_config_t ucl_compress_config_t
|
unsigned upx_crc32(const void *buf, unsigned len, unsigned crc=0);
|
||||||
#elif defined(WITH_NRV)
|
|
||||||
struct nrv_compress_config_t;
|
|
||||||
struct nrv_compress_config_t
|
|
||||||
{
|
|
||||||
int bb_endian;
|
|
||||||
int bb_size;
|
|
||||||
nrv_uint max_offset;
|
|
||||||
nrv_uint max_match;
|
|
||||||
int s_level;
|
|
||||||
int h_level;
|
|
||||||
int p_level;
|
|
||||||
int c_flags;
|
|
||||||
nrv_uint m_size;
|
|
||||||
};
|
|
||||||
#define upx_compress_config_t nrv_compress_config_t
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int upx_compress ( const upx_byte *src, upx_uint src_len,
|
int upx_compress ( const upx_bytep src, upx_uint src_len,
|
||||||
upx_byte *dst, upx_uint *dst_len,
|
upx_bytep dst, upx_uintp dst_len,
|
||||||
upx_progress_callback_t *cb,
|
upx_progress_callback_t *cb,
|
||||||
int method, int level,
|
int method, int level,
|
||||||
const struct upx_compress_config_t *conf,
|
const struct upx_compress_config_t *conf,
|
||||||
upx_uintp result );
|
upx_uintp result );
|
||||||
int upx_decompress ( const upx_byte *src, upx_uint src_len,
|
int upx_decompress ( const upx_bytep src, upx_uint src_len,
|
||||||
upx_byte *dst, upx_uint *dst_len,
|
upx_bytep dst, upx_uintp dst_len,
|
||||||
int method );
|
int method );
|
||||||
int upx_test_overlap ( const upx_byte *buf, upx_uint src_off,
|
int upx_test_overlap ( const upx_bytep buf, upx_uint src_off,
|
||||||
upx_uint src_len, upx_uint *dst_len,
|
upx_uint src_len, upx_uintp dst_len,
|
||||||
int method );
|
int method );
|
||||||
|
|
||||||
|
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+3
-14
@@ -29,12 +29,6 @@
|
|||||||
/* Define to `long' if <stddef.h> doesn't define. */
|
/* Define to `long' if <stddef.h> doesn't define. */
|
||||||
/* #undef ptrdiff_t */
|
/* #undef ptrdiff_t */
|
||||||
|
|
||||||
/* The number of bytes in a ptrdiff_t. */
|
|
||||||
#define SIZEOF_PTRDIFF_T 4
|
|
||||||
|
|
||||||
/* The number of bytes in a size_t. */
|
|
||||||
#define SIZEOF_SIZE_T 4
|
|
||||||
|
|
||||||
/* Define when using the dmalloc package. */
|
/* Define when using the dmalloc package. */
|
||||||
/* #undef WITH_DMALLOC */
|
/* #undef WITH_DMALLOC */
|
||||||
|
|
||||||
@@ -179,6 +173,9 @@
|
|||||||
/* Define if you have the <stddef.h> header file. */
|
/* Define if you have the <stddef.h> header file. */
|
||||||
#define HAVE_STDDEF_H 1
|
#define HAVE_STDDEF_H 1
|
||||||
|
|
||||||
|
/* Define if you have the <stdint.h> header file. */
|
||||||
|
#define HAVE_STDINT_H 1
|
||||||
|
|
||||||
/* Define if you have the <sys/param.h> header file. */
|
/* Define if you have the <sys/param.h> header file. */
|
||||||
#define HAVE_SYS_PARAM_H 1
|
#define HAVE_SYS_PARAM_H 1
|
||||||
|
|
||||||
@@ -225,14 +222,6 @@
|
|||||||
# undef /**/ HAVE_SYS_TIMES_H
|
# undef /**/ HAVE_SYS_TIMES_H
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (SIZEOF_PTRDIFF_T <= 0)
|
|
||||||
# undef /**/ SIZEOF_PTRDIFF_T
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (SIZEOF_SIZE_T <= 0)
|
|
||||||
# undef /**/ SIZEOF_SIZE_T
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* already included */
|
#endif /* already included */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -0,0 +1,226 @@
|
|||||||
|
/* pseudo <config.h> for sparc-sun-solaris2.8 */
|
||||||
|
|
||||||
|
#ifndef __UPX_CONFIG_H
|
||||||
|
#define __UPX_CONFIG_H
|
||||||
|
|
||||||
|
/* $TOP$ */
|
||||||
|
|
||||||
|
/* Define to empty if the keyword does not work. */
|
||||||
|
/* #undef const */
|
||||||
|
|
||||||
|
/* Define if your C compiler doesn't accept -c and -o together. */
|
||||||
|
/* #undef NO_MINUS_C_MINUS_O */
|
||||||
|
|
||||||
|
/* Define as the return type of signal handlers (int or void). */
|
||||||
|
#define RETSIGTYPE void
|
||||||
|
|
||||||
|
/* Define to `unsigned' if <sys/types.h> doesn't define. */
|
||||||
|
/* #undef size_t */
|
||||||
|
|
||||||
|
/* Define if you have the ANSI C header files. */
|
||||||
|
#define STDC_HEADERS 1
|
||||||
|
|
||||||
|
/* Define if you can safely include both <sys/time.h> and <time.h>. */
|
||||||
|
#define TIME_WITH_SYS_TIME 1
|
||||||
|
|
||||||
|
/* Define if your memcmp is broken. */
|
||||||
|
/* #undef NO_MEMCMP */
|
||||||
|
|
||||||
|
/* Define to `long' if <stddef.h> doesn't define. */
|
||||||
|
/* #undef ptrdiff_t */
|
||||||
|
|
||||||
|
/* Define when using the dmalloc package. */
|
||||||
|
/* #undef WITH_DMALLOC */
|
||||||
|
|
||||||
|
/* Define if you have the access function. */
|
||||||
|
#define HAVE_ACCESS 1
|
||||||
|
|
||||||
|
/* Define if you have the atoi function. */
|
||||||
|
#define HAVE_ATOI 1
|
||||||
|
|
||||||
|
/* Define if you have the chmod function. */
|
||||||
|
#define HAVE_CHMOD 1
|
||||||
|
|
||||||
|
/* Define if you have the chown function. */
|
||||||
|
#define HAVE_CHOWN 1
|
||||||
|
|
||||||
|
/* Define if you have the ctime function. */
|
||||||
|
#define HAVE_CTIME 1
|
||||||
|
|
||||||
|
/* Define if you have the difftime function. */
|
||||||
|
#define HAVE_DIFFTIME 1
|
||||||
|
|
||||||
|
/* Define if you have the fchmod function. */
|
||||||
|
#define HAVE_FCHMOD 1
|
||||||
|
|
||||||
|
/* Define if you have the fileno function. */
|
||||||
|
#define HAVE_FILENO 1
|
||||||
|
|
||||||
|
/* Define if you have the fstat function. */
|
||||||
|
#define HAVE_FSTAT 1
|
||||||
|
|
||||||
|
/* Define if you have the XXX function. */
|
||||||
|
#define HAVE_GETPID 1
|
||||||
|
|
||||||
|
/* Define if you have the XXX function. */
|
||||||
|
#define HAVE_GETTIMEOFDAY 1
|
||||||
|
|
||||||
|
/* Define if you have the getumask function. */
|
||||||
|
/* #undef HAVE_GETUMASK */
|
||||||
|
|
||||||
|
/* Define if you have the gmtime function. */
|
||||||
|
#define HAVE_GMTIME 1
|
||||||
|
|
||||||
|
/* Define if you have the index function. */
|
||||||
|
#define HAVE_INDEX 1
|
||||||
|
|
||||||
|
/* Define if you have the isatty function. */
|
||||||
|
#define HAVE_ISATTY 1
|
||||||
|
|
||||||
|
/* Define if you have the lstat function. */
|
||||||
|
#define HAVE_LSTAT 1
|
||||||
|
|
||||||
|
/* Define if you have the localtime function. */
|
||||||
|
#define HAVE_LOCALTIME 1
|
||||||
|
|
||||||
|
/* Define if you have the memcmp function. */
|
||||||
|
#define HAVE_MEMCMP 1
|
||||||
|
|
||||||
|
/* Define if you have the memcpy function. */
|
||||||
|
#define HAVE_MEMCPY 1
|
||||||
|
|
||||||
|
/* Define if you have the memmove function. */
|
||||||
|
#define HAVE_MEMMOVE 1
|
||||||
|
|
||||||
|
/* Define if you have the memset function. */
|
||||||
|
#define HAVE_MEMSET 1
|
||||||
|
|
||||||
|
/* Define if you have the mktime function. */
|
||||||
|
#define HAVE_MKTIME 1
|
||||||
|
|
||||||
|
/* Define if you have the setmode function. */
|
||||||
|
/* #undef HAVE_SETMODE */
|
||||||
|
|
||||||
|
/* Define if you have the stat function. */
|
||||||
|
#define HAVE_STAT 1
|
||||||
|
|
||||||
|
/* Define if you have the strcasecmp function. */
|
||||||
|
#define HAVE_STRCASECMP 1
|
||||||
|
|
||||||
|
/* Define if you have the strchr function. */
|
||||||
|
#define HAVE_STRCHR 1
|
||||||
|
|
||||||
|
/* Define if you have the strdup function. */
|
||||||
|
#define HAVE_STRDUP 1
|
||||||
|
|
||||||
|
/* Define if you have the strftime function. */
|
||||||
|
#define HAVE_STRFTIME 1
|
||||||
|
|
||||||
|
/* Define if you have the stricmp function. */
|
||||||
|
/* #undef HAVE_STRICMP */
|
||||||
|
|
||||||
|
/* Define if you have the strncasecmp function. */
|
||||||
|
#define HAVE_STRNCASECMP 1
|
||||||
|
|
||||||
|
/* Define if you have the strnicmp function. */
|
||||||
|
/* #undef HAVE_STRNICMP */
|
||||||
|
|
||||||
|
/* Define if you have the strstr function. */
|
||||||
|
#define HAVE_STRSTR 1
|
||||||
|
|
||||||
|
/* Define if you have the tzset function. */
|
||||||
|
#define HAVE_TZSET 1
|
||||||
|
|
||||||
|
/* Define if you have the umask function. */
|
||||||
|
#define HAVE_UMASK 1
|
||||||
|
|
||||||
|
/* Define if you have the utime function. */
|
||||||
|
#define HAVE_UTIME 1
|
||||||
|
|
||||||
|
/* Define if you have the vsnprintf function. */
|
||||||
|
#define HAVE_VSNPRINTF 1
|
||||||
|
|
||||||
|
/* Define if you have the <assert.h> header file. */
|
||||||
|
#define HAVE_ASSERT_H 1
|
||||||
|
|
||||||
|
/* Define if you have the <ctype.h> header file. */
|
||||||
|
#define HAVE_CTYPE_H 1
|
||||||
|
|
||||||
|
/* Define if you have the <curses.h> header file. */
|
||||||
|
#define HAVE_CURSES_H 1
|
||||||
|
|
||||||
|
/* Define if you have the <limits.h> header file. */
|
||||||
|
#define HAVE_LIMITS_H 1
|
||||||
|
|
||||||
|
/* Define if you have the <linux/kd.h> header file. */
|
||||||
|
#define HAVE_LINUX_KD_H 1
|
||||||
|
|
||||||
|
/* Define if you have the <linux/kdev_t.h> header file. */
|
||||||
|
#define HAVE_LINUX_KDEV_T_H 1
|
||||||
|
|
||||||
|
/* Define if you have the <linux/major.h> header file. */
|
||||||
|
#define HAVE_LINUX_MAJOR_H 1
|
||||||
|
|
||||||
|
/* Define if you have the <memory.h> header file. */
|
||||||
|
#define HAVE_MEMORY_H 1
|
||||||
|
|
||||||
|
/* Define if you have the <ncurses.h> header file. */
|
||||||
|
#define HAVE_NCURSES_H 1
|
||||||
|
|
||||||
|
/* Define if you have the <signal.h> header file. */
|
||||||
|
#define HAVE_SIGNAL_H 1
|
||||||
|
|
||||||
|
/* Define if you have the <stddef.h> header file. */
|
||||||
|
#define HAVE_STDDEF_H 1
|
||||||
|
|
||||||
|
/* Define if you have the <sys/param.h> header file. */
|
||||||
|
#define HAVE_SYS_PARAM_H 1
|
||||||
|
|
||||||
|
/* Define if you have the <sys/resource.h> header file. */
|
||||||
|
#define HAVE_SYS_RESOURCE_H 1
|
||||||
|
|
||||||
|
/* Define if you have the <sys/time.h> header file. */
|
||||||
|
#define HAVE_SYS_TIME_H 1
|
||||||
|
|
||||||
|
/* Define if you have the <sys/times.h> header file. */
|
||||||
|
#define HAVE_SYS_TIMES_H 1
|
||||||
|
|
||||||
|
/* Define if you have the <sys/utime.h> header file. */
|
||||||
|
/* #undef HAVE_SYS_UTIME_H */
|
||||||
|
|
||||||
|
/* Define if you have the <time.h> header file. */
|
||||||
|
#define HAVE_TIME_H 1
|
||||||
|
|
||||||
|
/* Define if you have the <unistd.h> header file. */
|
||||||
|
#define HAVE_UNISTD_H 1
|
||||||
|
|
||||||
|
/* Define if you have the <utime.h> header file. */
|
||||||
|
#define HAVE_UTIME_H 1
|
||||||
|
|
||||||
|
/* $BOTTOM$ */
|
||||||
|
|
||||||
|
#if defined(HAVE_GMTIME) && !defined(TIME_WITH_SYS_TIME)
|
||||||
|
# undef /**/ HAVE_GMTIME
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_LOCALTIME) && !defined(TIME_WITH_SYS_TIME)
|
||||||
|
# undef /**/ HAVE_LOCALTIME
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_STRFTIME) && !defined(TIME_WITH_SYS_TIME)
|
||||||
|
# undef /**/ HAVE_STRFTIME
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_SYS_RESOURCE_H) && !defined(TIME_WITH_SYS_TIME)
|
||||||
|
# undef /**/ HAVE_SYS_RESOURCE_H
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_SYS_TIMES_H) && !defined(TIME_WITH_SYS_TIME)
|
||||||
|
# undef /**/ HAVE_SYS_TIMES_H
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* already included */
|
||||||
|
|
||||||
|
/*
|
||||||
|
vi:ts=4
|
||||||
|
*/
|
||||||
+3
-3
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+48
-5
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,13 +22,54 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
long Throwable::counter = 0;
|
||||||
|
|
||||||
|
Throwable::Throwable(const char *m, int e, bool w)
|
||||||
|
: super(), msg(NULL), err(e), is_warning(w)
|
||||||
|
{
|
||||||
|
if (m)
|
||||||
|
msg = strdup(m);
|
||||||
|
#if 0
|
||||||
|
fprintf(stderr, "construct exception: %s %ld\n", msg, counter);
|
||||||
|
counter++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Throwable::Throwable(Throwable const &other)
|
||||||
|
: super(other), msg(NULL), err(other.err), is_warning(other.is_warning)
|
||||||
|
{
|
||||||
|
if (other.msg)
|
||||||
|
msg = strdup(other.msg);
|
||||||
|
#if 0
|
||||||
|
fprintf(stderr, "copy exception: %s %ld\n", msg, counter);
|
||||||
|
counter++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Throwable::~Throwable() NOTHROW
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
counter--;
|
||||||
|
fprintf(stderr, "destruct exception: %s %ld\n", msg, counter);
|
||||||
|
#endif
|
||||||
|
if (msg)
|
||||||
|
free(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// compression
|
// compression
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
@@ -135,14 +176,16 @@ void throwEOFException(const char *msg, int e)
|
|||||||
|
|
||||||
const char *prettyName(const char *n)
|
const char *prettyName(const char *n)
|
||||||
{
|
{
|
||||||
while (*n >= '0' && *n <= '9') // gcc / egcs
|
if (n == NULL)
|
||||||
|
return "";
|
||||||
|
while (*n >= '0' && *n <= '9') // gcc
|
||||||
n++;
|
n++;
|
||||||
if (strncmp(n, "class ", 6) == 0) // Visual C++
|
if (strncmp(n, "class ", 6) == 0) // Visual C++
|
||||||
n += 6;
|
n += 6;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *prettyName(const type_info &ti)
|
const char *prettyName(const std::type_info &ti)
|
||||||
{
|
{
|
||||||
return prettyName(ti.name());
|
return prettyName(ti.name());
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-20
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -32,31 +32,41 @@
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
const char *prettyName(const char *n);
|
const char *prettyName(const char *n);
|
||||||
const char *prettyName(const type_info &ti);
|
const char *prettyName(const std::type_info &ti);
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// exceptions
|
// exceptions
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
class Throwable : public exception
|
class Throwable : public std::exception
|
||||||
{
|
{
|
||||||
|
typedef std::exception super;
|
||||||
protected:
|
protected:
|
||||||
Throwable(const char *m = 0, int e = 0, bool w = false)
|
Throwable(const char *m = 0, int e = 0, bool w = false);
|
||||||
: msg(m), err(e), is_warning(w) { }
|
|
||||||
public:
|
public:
|
||||||
virtual ~Throwable() { }
|
Throwable(Throwable const &);
|
||||||
|
virtual ~Throwable() NOTHROW;
|
||||||
const char *getMsg() const { return msg; }
|
const char *getMsg() const { return msg; }
|
||||||
int getErrno() const { return err; }
|
int getErrno() const { return err; }
|
||||||
bool isWarning() const { return is_warning; }
|
bool isWarning() const { return is_warning; }
|
||||||
private:
|
private:
|
||||||
//Throwable(const Throwable &);
|
char *msg;
|
||||||
private:
|
|
||||||
// void * operator new(size_t); // ...
|
|
||||||
const char *msg;
|
|
||||||
int err;
|
int err;
|
||||||
protected:
|
protected:
|
||||||
bool is_warning; // can be set by subclasses
|
bool is_warning; // can be set by subclasses
|
||||||
|
|
||||||
|
private:
|
||||||
|
// disable assignment
|
||||||
|
Throwable& operator= (Throwable const &);
|
||||||
|
// disable dynamic allocation
|
||||||
|
#ifndef new
|
||||||
|
static void *operator new (size_t); // {}
|
||||||
|
static void *operator new[] (size_t); // {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
static long counter; // for debugging
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -196,25 +206,25 @@ public:
|
|||||||
#undef NORET
|
#undef NORET
|
||||||
#if 0 && defined(__GNUC__)
|
#if 0 && defined(__GNUC__)
|
||||||
// (noreturn) is probably not the correct semantics for throwing exceptions
|
// (noreturn) is probably not the correct semantics for throwing exceptions
|
||||||
#define NORET __attribute__((noreturn))
|
#define NORET __attribute__((__noreturn__))
|
||||||
#else
|
#else
|
||||||
#define NORET
|
#define NORET
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void throwCantPack(const char *msg) NORET;
|
void throwCantPack(const char *msg) NORET;
|
||||||
void throwUnknownExecutableFormat(const char *msg = 0, bool warn = false) NORET;
|
void throwUnknownExecutableFormat(const char *msg = NULL, bool warn = false) NORET;
|
||||||
void throwNotCompressible(const char *msg = 0) NORET;
|
void throwNotCompressible(const char *msg = NULL) NORET;
|
||||||
void throwAlreadyPacked(const char *msg = 0) NORET;
|
void throwAlreadyPacked(const char *msg = NULL) NORET;
|
||||||
void throwAlreadyPackedByUPX(const char *msg = 0) NORET;
|
void throwAlreadyPackedByUPX(const char *msg = NULL) NORET;
|
||||||
void throwCantUnpack(const char *msg) NORET;
|
void throwCantUnpack(const char *msg) NORET;
|
||||||
void throwNotPacked(const char *msg = 0) NORET;
|
void throwNotPacked(const char *msg = NULL) NORET;
|
||||||
void throwFilterException() NORET;
|
void throwFilterException() NORET;
|
||||||
void throwBadLoader() NORET;
|
void throwBadLoader() NORET;
|
||||||
void throwChecksumError() NORET;
|
void throwChecksumError() NORET;
|
||||||
void throwCompressedDataViolation() NORET;
|
void throwCompressedDataViolation() NORET;
|
||||||
void throwInternalError(const char *msg) NORET;
|
void throwInternalError(const char *msg) NORET;
|
||||||
void throwIOException(const char *msg = 0, int e = 0) NORET;
|
void throwIOException(const char *msg = NULL, int e = 0) NORET;
|
||||||
void throwEOFException(const char *msg = 0, int e = 0) NORET;
|
void throwEOFException(const char *msg = NULL, int e = 0) NORET;
|
||||||
|
|
||||||
#undef NORET
|
#undef NORET
|
||||||
|
|
||||||
|
|||||||
-125
@@ -1,125 +0,0 @@
|
|||||||
/* fctl_ml.ch -- filter CTO implementation
|
|
||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
|
||||||
All Rights Reserved.
|
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
|
||||||
and/or modify them under the terms of the GNU General Public License as
|
|
||||||
published by the Free Software Foundation; either version 2 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; see the file COPYING.
|
|
||||||
If not, write to the Free Software Foundation, Inc.,
|
|
||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
// these are not implemented here
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
// filter: e8, e9, e8e9
|
|
||||||
#define f_cto32_e8 NULL
|
|
||||||
#define f_cto32_e9 NULL
|
|
||||||
#define f_cto32_e8e9 NULL
|
|
||||||
|
|
||||||
// unfilter: e8, e9, e8e9
|
|
||||||
#define u_cto32_e8 NULL
|
|
||||||
#define u_cto32_e9 NULL
|
|
||||||
#define u_cto32_e8e9 NULL
|
|
||||||
|
|
||||||
// scan: e8, e9, e8e9
|
|
||||||
#define s_cto32_e8 NULL
|
|
||||||
#define s_cto32_e9 NULL
|
|
||||||
#define s_cto32_e8e9 NULL
|
|
||||||
|
|
||||||
// filter: e8, e9, e8e9 with bswap be->le
|
|
||||||
#define f_cto32_e8_bswap_be NULL
|
|
||||||
#define f_cto32_e9_bswap_be NULL
|
|
||||||
#define f_cto32_e8e9_bswap_be NULL
|
|
||||||
|
|
||||||
// unfilter: e8, e9, e8e9 with bswap be->le
|
|
||||||
#define u_cto32_e8_bswap_be NULL
|
|
||||||
#define u_cto32_e9_bswap_be NULL
|
|
||||||
#define u_cto32_e8e9_bswap_be NULL
|
|
||||||
|
|
||||||
// scan: e8, e9, e8e9 with bswap be->le
|
|
||||||
#define s_cto32_e8_bswap_be NULL
|
|
||||||
#define s_cto32_e9_bswap_be NULL
|
|
||||||
#define s_cto32_e8e9_bswap_be NULL
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
//
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
#define COND(b,x) (b[x] == 0xe8)
|
|
||||||
#define F f_cto32_e8_bswap_le
|
|
||||||
#define U u_cto32_e8_bswap_le
|
|
||||||
#include "fcto_ml2.ch"
|
|
||||||
#undef U
|
|
||||||
#undef F
|
|
||||||
#define F s_cto32_e8_bswap_le
|
|
||||||
#include "fcto_ml2.ch"
|
|
||||||
#undef F
|
|
||||||
#undef COND
|
|
||||||
|
|
||||||
#define COND(b,x) (b[x] == 0xe9)
|
|
||||||
#define F f_cto32_e9_bswap_le
|
|
||||||
#define U u_cto32_e9_bswap_le
|
|
||||||
#include "fcto_ml2.ch"
|
|
||||||
#undef U
|
|
||||||
#undef F
|
|
||||||
#define F s_cto32_e9_bswap_le
|
|
||||||
#include "fcto_ml2.ch"
|
|
||||||
#undef F
|
|
||||||
#undef COND
|
|
||||||
|
|
||||||
#define COND(b,x) (b[x] == 0xe8 || b[x] == 0xe9)
|
|
||||||
#define F f_cto32_e8e9_bswap_le
|
|
||||||
#define U u_cto32_e8e9_bswap_le
|
|
||||||
#include "fcto_ml2.ch"
|
|
||||||
#undef U
|
|
||||||
#undef F
|
|
||||||
#define F s_cto32_e8e9_bswap_le
|
|
||||||
#include "fcto_ml2.ch"
|
|
||||||
#undef F
|
|
||||||
#undef COND
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
//
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
#define COND(b,x,lastcall) (b[x] == 0xe8 || b[x] == 0xe9 \
|
|
||||||
|| (lastcall!=(x) && 0xf==b[(x)-1] \
|
|
||||||
&& 0x80<=b[x] && b[x]<=0x8f) )
|
|
||||||
#define F f_ctjo32_e8e9_bswap_le
|
|
||||||
#define U u_ctjo32_e8e9_bswap_le
|
|
||||||
#include "fcto_ml3.ch"
|
|
||||||
#undef U
|
|
||||||
#undef F
|
|
||||||
#define F s_ctjo32_e8e9_bswap_le
|
|
||||||
#include "fcto_ml3.ch"
|
|
||||||
#undef F
|
|
||||||
#undef COND
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
vi:ts=4:et
|
|
||||||
*/
|
|
||||||
|
|
||||||
+64
-28
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,12 +22,13 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
#include "mem.h"
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
@@ -85,6 +86,25 @@ FileBase::~FileBase()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FileBase::sopen()
|
||||||
|
{
|
||||||
|
if (_shflags < 0)
|
||||||
|
_fd = ::open(_name, _flags, _mode);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if defined(__DJGPP__)
|
||||||
|
_fd = ::open(_name,_flags | _shflags, _mode);
|
||||||
|
#elif defined(__MINT__)
|
||||||
|
_fd = ::open(_name,_flags | (_shflags & O_SHMODE), _mode);
|
||||||
|
#elif defined(SH_DENYRW)
|
||||||
|
_fd = ::sopen(_name, _flags, _shflags, _mode);
|
||||||
|
#else
|
||||||
|
assert(0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool FileBase::close()
|
bool FileBase::close()
|
||||||
{
|
{
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
@@ -171,13 +191,17 @@ void FileBase::write(const void *buf, int len)
|
|||||||
void FileBase::seek(off_t off, int whence)
|
void FileBase::seek(off_t off, int whence)
|
||||||
{
|
{
|
||||||
if (!isOpen())
|
if (!isOpen())
|
||||||
throwIOException("bad seek");
|
throwIOException("bad seek 1");
|
||||||
|
if (whence == SEEK_SET && off < 0)
|
||||||
|
throwIOException("bad seek 2");
|
||||||
|
if (whence == SEEK_END && off > 0)
|
||||||
|
throwIOException("bad seek 3");
|
||||||
if (::lseek(_fd,off,whence) < 0)
|
if (::lseek(_fd,off,whence) < 0)
|
||||||
throwIOException("seek error",errno);
|
throwIOException("seek error",errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
off_t FileBase::tell()
|
off_t FileBase::tell() const
|
||||||
{
|
{
|
||||||
if (!isOpen())
|
if (!isOpen())
|
||||||
throwIOException("bad tell");
|
throwIOException("bad tell");
|
||||||
@@ -209,16 +233,7 @@ void InputFile::sopen(const char *name, int flags, int shflags)
|
|||||||
_flags = flags;
|
_flags = flags;
|
||||||
_shflags = shflags;
|
_shflags = shflags;
|
||||||
_mode = 0;
|
_mode = 0;
|
||||||
if (shflags < 0)
|
FileBase::sopen();
|
||||||
_fd = ::open(_name,_flags);
|
|
||||||
else
|
|
||||||
#if defined(__DJGPP__)
|
|
||||||
_fd = ::open(_name,_flags | _shflags);
|
|
||||||
#elif defined(SH_DENYRW)
|
|
||||||
_fd = ::sopen(_name,_flags,_shflags);
|
|
||||||
#else
|
|
||||||
assert(0);
|
|
||||||
#endif
|
|
||||||
if (!isOpen())
|
if (!isOpen())
|
||||||
{
|
{
|
||||||
if (errno == ENOENT)
|
if (errno == ENOENT)
|
||||||
@@ -236,20 +251,43 @@ int InputFile::read(void *buf, int len)
|
|||||||
return super::read(buf, len);
|
return super::read(buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int InputFile::readx(void *buf, int len)
|
int InputFile::readx(void *buf, int len)
|
||||||
{
|
{
|
||||||
return super::readx(buf, len);
|
return super::readx(buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int InputFile::read(MemBuffer *buf, int len)
|
||||||
|
{
|
||||||
|
assert((unsigned)len <= buf->getSize());
|
||||||
|
return super::read(buf->getVoidPtr(), len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int InputFile::readx(MemBuffer *buf, int len)
|
||||||
|
{
|
||||||
|
assert((unsigned)len <= buf->getSize());
|
||||||
|
return super::readx(buf->getVoidPtr(), len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int InputFile::read(MemBuffer &buf, int len)
|
||||||
|
{
|
||||||
|
return read(&buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int InputFile::readx(MemBuffer &buf, int len)
|
||||||
|
{
|
||||||
|
return readx(&buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void InputFile::seek(off_t off, int whence)
|
void InputFile::seek(off_t off, int whence)
|
||||||
{
|
{
|
||||||
super::seek(off,whence);
|
super::seek(off,whence);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
off_t InputFile::tell()
|
off_t InputFile::tell() const
|
||||||
{
|
{
|
||||||
return super::tell();
|
return super::tell();
|
||||||
}
|
}
|
||||||
@@ -277,16 +315,7 @@ void OutputFile::sopen(const char *name, int flags, int shflags, int mode)
|
|||||||
_flags = flags;
|
_flags = flags;
|
||||||
_shflags = shflags;
|
_shflags = shflags;
|
||||||
_mode = mode;
|
_mode = mode;
|
||||||
if (shflags < 0)
|
FileBase::sopen();
|
||||||
_fd = ::open(_name,_flags,_mode);
|
|
||||||
else
|
|
||||||
#if defined(__DJGPP__)
|
|
||||||
_fd = ::open(_name,_flags | _shflags, _mode);
|
|
||||||
#elif defined(SH_DENYRW)
|
|
||||||
_fd = ::sopen(_name,_flags,_shflags,_mode);
|
|
||||||
#else
|
|
||||||
assert(0);
|
|
||||||
#endif
|
|
||||||
if (!isOpen())
|
if (!isOpen())
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
@@ -319,7 +348,9 @@ bool OutputFile::openStdout(int flags, bool force)
|
|||||||
if (flags != 0)
|
if (flags != 0)
|
||||||
{
|
{
|
||||||
assert(flags == O_BINARY);
|
assert(flags == O_BINARY);
|
||||||
#if defined(HAVE_SETMODE) && defined(USE_SETMODE)
|
#if defined(__MINT__)
|
||||||
|
__set_binmode(stdout, 1);
|
||||||
|
#elif defined(HAVE_SETMODE) && defined(USE_SETMODE)
|
||||||
if (setmode(_fd, O_BINARY) == -1)
|
if (setmode(_fd, O_BINARY) == -1)
|
||||||
throwIOException(_name,errno);
|
throwIOException(_name,errno);
|
||||||
#if defined(__DJGPP__)
|
#if defined(__DJGPP__)
|
||||||
@@ -354,6 +385,8 @@ void OutputFile::dump(const char *name, const void *buf, int len, int flags)
|
|||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
MemoryOutputFile::MemoryOutputFile() :
|
MemoryOutputFile::MemoryOutputFile() :
|
||||||
b(NULL), b_size(0), b_pos(0), bytes_written(0)
|
b(NULL), b_size(0), b_pos(0), bytes_written(0)
|
||||||
{
|
{
|
||||||
@@ -374,6 +407,9 @@ void MemoryOutputFile::write(const void *buf, int len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* if 0 */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
vi:ts=4:et
|
vi:ts=4:et
|
||||||
*/
|
*/
|
||||||
|
|||||||
+18
-5
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,13 +22,15 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef __UPX_FILE_H
|
#ifndef __UPX_FILE_H
|
||||||
#define __UPX_FILE_H
|
#define __UPX_FILE_H
|
||||||
|
|
||||||
|
class MemBuffer;
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
//
|
||||||
@@ -56,11 +58,12 @@ public:
|
|||||||
const char *getName() const { return _name; }
|
const char *getName() const { return _name; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void sopen();
|
||||||
virtual int read(void *buf, int len);
|
virtual int read(void *buf, int len);
|
||||||
virtual int readx(void *buf, int len);
|
virtual int readx(void *buf, int len);
|
||||||
virtual void write(const void *buf, int len);
|
virtual void write(const void *buf, int len);
|
||||||
virtual void seek(off_t off, int whence);
|
virtual void seek(off_t off, int whence);
|
||||||
virtual off_t tell();
|
virtual off_t tell() const;
|
||||||
|
|
||||||
int _fd;
|
int _fd;
|
||||||
int _flags;
|
int _flags;
|
||||||
@@ -91,9 +94,13 @@ public:
|
|||||||
|
|
||||||
virtual int read(void *buf, int len);
|
virtual int read(void *buf, int len);
|
||||||
virtual int readx(void *buf, int len);
|
virtual int readx(void *buf, int len);
|
||||||
|
virtual int read(MemBuffer *buf, int len);
|
||||||
|
virtual int readx(MemBuffer *buf, int len);
|
||||||
|
virtual int read(MemBuffer &buf, int len);
|
||||||
|
virtual int readx(MemBuffer &buf, int len);
|
||||||
|
|
||||||
virtual void seek(off_t off, int whence);
|
virtual void seek(off_t off, int whence);
|
||||||
virtual off_t tell();
|
virtual off_t tell() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -119,16 +126,20 @@ public:
|
|||||||
|
|
||||||
off_t getBytesWritten() const { return bytes_written; }
|
off_t getBytesWritten() const { return bytes_written; }
|
||||||
|
|
||||||
|
#if (UPX_VERSION_HEX >= 0x019000)
|
||||||
// FIXME - these won't work when using the `--stdout' option
|
// FIXME - these won't work when using the `--stdout' option
|
||||||
virtual void seek(off_t off, int whence)
|
virtual void seek(off_t off, int whence)
|
||||||
{
|
{
|
||||||
|
assert(!opt->to_stdout);
|
||||||
super::seek(off,whence);
|
super::seek(off,whence);
|
||||||
}
|
}
|
||||||
virtual void rewrite(const void *buf, int len)
|
virtual void rewrite(const void *buf, int len)
|
||||||
{
|
{
|
||||||
|
assert(!opt->to_stdout);
|
||||||
write(buf, len);
|
write(buf, len);
|
||||||
bytes_written -= len; // restore
|
bytes_written -= len; // restore
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// util
|
// util
|
||||||
static void dump(const char *name, const void *buf, int len, int flags=-1);
|
static void dump(const char *name, const void *buf, int len, int flags=-1);
|
||||||
@@ -142,6 +153,7 @@ protected:
|
|||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
#if 0
|
||||||
class MemoryOutputFile : public FileBase
|
class MemoryOutputFile : public FileBase
|
||||||
{
|
{
|
||||||
typedef FileBase super;
|
typedef FileBase super;
|
||||||
@@ -164,6 +176,7 @@ protected:
|
|||||||
unsigned b_pos;
|
unsigned b_pos;
|
||||||
off_t bytes_written;
|
off_t bytes_written;
|
||||||
};
|
};
|
||||||
|
#endif /* if 0 */
|
||||||
|
|
||||||
|
|
||||||
#endif /* already included */
|
#endif /* already included */
|
||||||
|
|||||||
+25
-21
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,12 +22,13 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
|
#include "file.h"
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
@@ -40,7 +41,7 @@ void initFilter(Filter *f, upx_byte *buf, unsigned buf_len)
|
|||||||
f->buf = buf;
|
f->buf = buf;
|
||||||
f->buf_len = buf_len;
|
f->buf_len = buf_len;
|
||||||
// clear output parameters
|
// clear output parameters
|
||||||
f->calls = f->wrongcalls = f->noncalls = f->lastcall = 0;
|
f->calls = f->wrongcalls = f->noncalls = f->firstcall = f->lastcall = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -78,6 +79,13 @@ const FilterImp::FilterEntry *FilterImp::getFilter(int id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Filter::isValidFilter(int filter_id)
|
||||||
|
{
|
||||||
|
const FilterImp::FilterEntry * const fe = FilterImp::getFilter(filter_id);
|
||||||
|
return fe != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// high level API
|
// high level API
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
@@ -88,10 +96,10 @@ void Filter::init(int id_, unsigned addvalue_)
|
|||||||
initFilter(this, NULL, 0);
|
initFilter(this, NULL, 0);
|
||||||
// clear input parameters
|
// clear input parameters
|
||||||
this->addvalue = addvalue_;
|
this->addvalue = addvalue_;
|
||||||
this->forced_cto = -1;
|
|
||||||
this->preferred_ctos = NULL;
|
this->preferred_ctos = NULL;
|
||||||
// clear input/output parameters
|
// clear input/output parameters
|
||||||
this->cto = 0;
|
this->cto = 0;
|
||||||
|
this->n_mru = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -112,13 +120,12 @@ bool Filter::filter(upx_byte *buf_, unsigned buf_len_)
|
|||||||
throwInternalError("filter-2");
|
throwInternalError("filter-2");
|
||||||
|
|
||||||
// save checksum
|
// save checksum
|
||||||
|
this->adler = 0;
|
||||||
if (clevel != 1)
|
if (clevel != 1)
|
||||||
{
|
this->adler = upx_adler32(this->buf, this->buf_len);
|
||||||
this->adler = upx_adler32(0,NULL,0);
|
|
||||||
this->adler = upx_adler32(this->adler, this->buf, this->buf_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
//printf("filter: %02x %p %d\n", this->id, this->buf, this->buf_len);
|
//printf("filter: %02x %p %d\n", this->id, this->buf, this->buf_len);
|
||||||
|
//OutputFile::dump("filter.dat", buf, buf_len);
|
||||||
int r = (*fe->do_filter)(this);
|
int r = (*fe->do_filter)(this);
|
||||||
//printf("filter: %02x %d\n", fe->id, r);
|
//printf("filter: %02x %d\n", fe->id, r);
|
||||||
if (r > 0)
|
if (r > 0)
|
||||||
@@ -129,7 +136,7 @@ bool Filter::filter(upx_byte *buf_, unsigned buf_len_)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Filter::unfilter(upx_byte *buf_, unsigned buf_len_, bool verify_checksum)
|
void Filter::unfilter(upx_byte *buf_, unsigned buf_len_, bool verify_checksum)
|
||||||
{
|
{
|
||||||
initFilter(this, buf_, buf_len_);
|
initFilter(this, buf_, buf_len_);
|
||||||
|
|
||||||
@@ -137,11 +144,11 @@ bool Filter::unfilter(upx_byte *buf_, unsigned buf_len_, bool verify_checksum)
|
|||||||
if (fe == NULL)
|
if (fe == NULL)
|
||||||
throwInternalError("unfilter-1");
|
throwInternalError("unfilter-1");
|
||||||
if (fe->id == 0)
|
if (fe->id == 0)
|
||||||
return true;
|
return;
|
||||||
if (buf_len < fe->min_buf_len)
|
if (buf_len < fe->min_buf_len)
|
||||||
return false;
|
return;
|
||||||
if (fe->max_buf_len && buf_len > fe->max_buf_len)
|
if (fe->max_buf_len && buf_len > fe->max_buf_len)
|
||||||
return false;
|
return;
|
||||||
if (!fe->do_unfilter)
|
if (!fe->do_unfilter)
|
||||||
throwInternalError("unfilter-2");
|
throwInternalError("unfilter-2");
|
||||||
|
|
||||||
@@ -150,20 +157,18 @@ bool Filter::unfilter(upx_byte *buf_, unsigned buf_len_, bool verify_checksum)
|
|||||||
//printf("unfilter: %02x %d\n", fe->id, r);
|
//printf("unfilter: %02x %d\n", fe->id, r);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
throwInternalError("unfilter-3");
|
throwInternalError("unfilter-3");
|
||||||
|
//OutputFile::dump("unfilter.dat", buf, buf_len);
|
||||||
|
|
||||||
// verify checksum
|
// verify checksum
|
||||||
if (verify_checksum && clevel != 1)
|
if (verify_checksum && clevel != 1)
|
||||||
{
|
{
|
||||||
unsigned a = upx_adler32(0,NULL,0);
|
if (this->adler != upx_adler32(this->buf, this->buf_len))
|
||||||
if (this->adler != upx_adler32(a, this->buf, this->buf_len))
|
|
||||||
throwInternalError("unfilter-4");
|
throwInternalError("unfilter-4");
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Filter::verifyUnfilter()
|
void Filter::verifyUnfilter()
|
||||||
{
|
{
|
||||||
// Note:
|
// Note:
|
||||||
// This verify is just because of complete paranoia that there
|
// This verify is just because of complete paranoia that there
|
||||||
@@ -175,9 +180,8 @@ bool Filter::verifyUnfilter()
|
|||||||
// Packer::verifyOverlappingDecompression()
|
// Packer::verifyOverlappingDecompression()
|
||||||
|
|
||||||
//printf("verifyUnfilter: %02x %p %d\n", this->id, this->buf, this->buf_len);
|
//printf("verifyUnfilter: %02x %p %d\n", this->id, this->buf, this->buf_len);
|
||||||
if (clevel == 1)
|
if (clevel != 1)
|
||||||
return true;
|
unfilter(this->buf, this->buf_len, true);
|
||||||
return unfilter(this->buf, this->buf_len, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+10
-8
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -44,8 +44,7 @@ class FilterImp;
|
|||||||
// call throwFilterException() - this will cause the compression
|
// call throwFilterException() - this will cause the compression
|
||||||
// to fail.
|
// to fail.
|
||||||
//
|
//
|
||||||
// The return value of unfilters can/should be ignored. They throw
|
// Unfilters throw exceptions in case of errors.
|
||||||
// exceptions in case of errors.
|
|
||||||
//
|
//
|
||||||
// The main idea behind filters is to convert relative jumps and calls
|
// The main idea behind filters is to convert relative jumps and calls
|
||||||
// to absolute addresses so that the buffer compresses better.
|
// to absolute addresses so that the buffer compresses better.
|
||||||
@@ -58,10 +57,12 @@ public:
|
|||||||
void init(int id=0, unsigned addvalue=0);
|
void init(int id=0, unsigned addvalue=0);
|
||||||
|
|
||||||
bool filter(upx_byte *buf, unsigned buf_len);
|
bool filter(upx_byte *buf, unsigned buf_len);
|
||||||
bool unfilter(upx_byte *buf, unsigned buf_len, bool verify_checksum=false);
|
void unfilter(upx_byte *buf, unsigned buf_len, bool verify_checksum=false);
|
||||||
bool verifyUnfilter();
|
void verifyUnfilter();
|
||||||
bool scan(const upx_byte *buf, unsigned buf_len);
|
bool scan(const upx_byte *buf, unsigned buf_len);
|
||||||
|
|
||||||
|
static bool isValidFilter(int filter_id);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Will be set by each call to filter()/unfilter().
|
// Will be set by each call to filter()/unfilter().
|
||||||
// Read-only afterwards.
|
// Read-only afterwards.
|
||||||
@@ -74,7 +75,6 @@ public:
|
|||||||
|
|
||||||
// Input parameters used by various filters.
|
// Input parameters used by various filters.
|
||||||
unsigned addvalue;
|
unsigned addvalue;
|
||||||
int forced_cto;
|
|
||||||
const int *preferred_ctos;
|
const int *preferred_ctos;
|
||||||
|
|
||||||
// Input/output parameters used by various filters
|
// Input/output parameters used by various filters
|
||||||
@@ -84,7 +84,9 @@ public:
|
|||||||
unsigned calls;
|
unsigned calls;
|
||||||
unsigned noncalls;
|
unsigned noncalls;
|
||||||
unsigned wrongcalls;
|
unsigned wrongcalls;
|
||||||
|
unsigned firstcall;
|
||||||
unsigned lastcall;
|
unsigned lastcall;
|
||||||
|
unsigned n_mru; // ctojr only
|
||||||
|
|
||||||
// Read only.
|
// Read only.
|
||||||
int id;
|
int id;
|
||||||
|
|||||||
+390
@@ -0,0 +1,390 @@
|
|||||||
|
/* ct.h -- calltrick filter
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// 16-bit calltrick ("naive")
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#define CT16(f, cond, addvalue, get, set) \
|
||||||
|
upx_byte *b = f->buf; \
|
||||||
|
upx_byte *b_end = b + f->buf_len - 3; \
|
||||||
|
do { \
|
||||||
|
if (cond) \
|
||||||
|
{ \
|
||||||
|
b += 1; \
|
||||||
|
unsigned a = (unsigned) (b - f->buf); \
|
||||||
|
f->lastcall = a; \
|
||||||
|
set(b, get(b) + (addvalue)); \
|
||||||
|
f->calls++; \
|
||||||
|
b += 2 - 1; \
|
||||||
|
} \
|
||||||
|
} while (++b < b_end); \
|
||||||
|
if (f->lastcall) f->lastcall += 2; \
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// filter: e8, e9, e8e9
|
||||||
|
static int f_ct16_e8(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe8), a + f->addvalue, get_le16, set_le16)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_ct16_e9(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe9), a + f->addvalue, get_le16, set_le16)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_ct16_e8e9(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le16, set_le16)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// unfilter: e8, e9, e8e9
|
||||||
|
static int u_ct16_e8(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe8), 0 - a - f->addvalue, get_le16, set_le16)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_ct16_e9(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe9), 0 - a - f->addvalue, get_le16, set_le16)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_ct16_e8e9(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_le16, set_le16)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// scan: e8, e9, e8e9
|
||||||
|
static int s_ct16_e8(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe8), a + f->addvalue, get_le16, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_ct16_e9(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe9), a + f->addvalue, get_le16, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_ct16_e8e9(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le16, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// filter: e8, e9, e8e9 with bswap le->be
|
||||||
|
static int f_ct16_e8_bswap_le(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe8), a + f->addvalue, get_le16, set_be16)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_ct16_e9_bswap_le(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe9), a + f->addvalue, get_le16, set_be16)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_ct16_e8e9_bswap_le(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le16, set_be16)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// unfilter: e8, e9, e8e9 with bswap le->be
|
||||||
|
static int u_ct16_e8_bswap_le(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe8), 0 - a - f->addvalue, get_be16, set_le16)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_ct16_e9_bswap_le(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe9), 0 - a - f->addvalue, get_be16, set_le16)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_ct16_e8e9_bswap_le(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_be16, set_le16)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// scan: e8, e9, e8e9 with bswap le->be
|
||||||
|
static int s_ct16_e8_bswap_le(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe8), a + f->addvalue, get_be16, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_ct16_e9_bswap_le(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe9), a + f->addvalue, get_be16, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_ct16_e8e9_bswap_le(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_be16, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// filter: e8, e9, e8e9 with bswap be->le
|
||||||
|
static int f_ct16_e8_bswap_be(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe8), a + f->addvalue, get_be16, set_le16)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_ct16_e9_bswap_be(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe9), a + f->addvalue, get_be16, set_le16)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_ct16_e8e9_bswap_be(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_be16, set_le16)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// unfilter: e8, e9, e8e9 with bswap be->le
|
||||||
|
static int u_ct16_e8_bswap_be(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe8), 0 - a - f->addvalue, get_le16, set_be16)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_ct16_e9_bswap_be(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe9), 0 - a - f->addvalue, get_le16, set_be16)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_ct16_e8e9_bswap_be(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_le16, set_be16)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// scan: e8, e9, e8e9 with bswap be->le
|
||||||
|
static int s_ct16_e8_bswap_be(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe8), a + f->addvalue, get_le16, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_ct16_e9_bswap_be(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe9), a + f->addvalue, get_le16, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_ct16_e8e9_bswap_be(Filter *f)
|
||||||
|
{
|
||||||
|
CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le16, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#undef CT16
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// 32-bit calltrick ("naive")
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#define CT32(f, cond, addvalue, get, set) \
|
||||||
|
upx_byte *b = f->buf; \
|
||||||
|
upx_byte *b_end = b + f->buf_len - 5; \
|
||||||
|
do { \
|
||||||
|
if (cond) \
|
||||||
|
{ \
|
||||||
|
b += 1; \
|
||||||
|
unsigned a = (unsigned) (b - f->buf); \
|
||||||
|
f->lastcall = a; \
|
||||||
|
set(b, get(b) + (addvalue)); \
|
||||||
|
f->calls++; \
|
||||||
|
b += 4 - 1; \
|
||||||
|
} \
|
||||||
|
} while (++b < b_end); \
|
||||||
|
if (f->lastcall) f->lastcall += 4; \
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
|
// filter: e8, e9, e8e9
|
||||||
|
static int f_ct32_e8(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe8), a + f->addvalue, get_le32, set_le32)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_ct32_e9(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe9), a + f->addvalue, get_le32, set_le32)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_ct32_e8e9(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le32, set_le32)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// unfilter: e8, e9, e8e9
|
||||||
|
static int u_ct32_e8(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe8), 0 - a - f->addvalue, get_le32, set_le32)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_ct32_e9(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe9), 0 - a - f->addvalue, get_le32, set_le32)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_ct32_e8e9(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_le32, set_le32)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// scan: e8, e9, e8e9
|
||||||
|
static int s_ct32_e8(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe8), a + f->addvalue, get_le32, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_ct32_e9(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe9), a + f->addvalue, get_le32, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_ct32_e8e9(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le32, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// filter: e8, e9, e8e9 with bswap le->be
|
||||||
|
static int f_ct32_e8_bswap_le(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe8), a + f->addvalue, get_le32, set_be32)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_ct32_e9_bswap_le(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe9), a + f->addvalue, get_le32, set_be32)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_ct32_e8e9_bswap_le(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le32, set_be32)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// unfilter: e8, e9, e8e9 with bswap le->be
|
||||||
|
static int u_ct32_e8_bswap_le(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe8), 0 - a - f->addvalue, get_be32, set_le32)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_ct32_e9_bswap_le(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe9), 0 - a - f->addvalue, get_be32, set_le32)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_ct32_e8e9_bswap_le(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_be32, set_le32)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// scan: e8, e9, e8e9 with bswap le->be
|
||||||
|
static int s_ct32_e8_bswap_le(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe8), a + f->addvalue, get_be32, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_ct32_e9_bswap_le(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe9), a + f->addvalue, get_be32, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_ct32_e8e9_bswap_le(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_be32, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// filter: e8, e9, e8e9 with bswap be->le
|
||||||
|
static int f_ct32_e8_bswap_be(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe8), a + f->addvalue, get_be32, set_le32)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_ct32_e9_bswap_be(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe9), a + f->addvalue, get_be32, set_le32)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_ct32_e8e9_bswap_be(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_be32, set_le32)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// unfilter: e8, e9, e8e9 with bswap be->le
|
||||||
|
static int u_ct32_e8_bswap_be(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe8), 0 - a - f->addvalue, get_le32, set_be32)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_ct32_e9_bswap_be(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe9), 0 - a - f->addvalue, get_le32, set_be32)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_ct32_e8e9_bswap_be(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_le32, set_be32)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// scan: e8, e9, e8e9 with bswap be->le
|
||||||
|
static int s_ct32_e8_bswap_be(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe8), a + f->addvalue, get_le32, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_ct32_e9_bswap_be(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe9), a + f->addvalue, get_le32, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_ct32_e8e9_bswap_be(Filter *f)
|
||||||
|
{
|
||||||
|
CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le32, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#undef CT32
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
vi:ts=4:et:nowrap
|
||||||
|
*/
|
||||||
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
/* fctl_ml2.ch -- filter CTO implementation
|
/* cto.h -- calltrick filter
|
||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,13 +22,13 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
// filter / scan
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
static int F(Filter *f)
|
static int F(Filter *f)
|
||||||
@@ -44,64 +44,27 @@ static int F(Filter *f)
|
|||||||
const unsigned size = f->buf_len;
|
const unsigned size = f->buf_len;
|
||||||
|
|
||||||
unsigned ic, jc, kc;
|
unsigned ic, jc, kc;
|
||||||
unsigned cto;
|
|
||||||
unsigned char cto8;
|
|
||||||
unsigned calls = 0, noncalls = 0, noncalls2 = 0;
|
unsigned calls = 0, noncalls = 0, noncalls2 = 0;
|
||||||
unsigned lastnoncall = size, lastcall = 0;
|
unsigned lastnoncall = size, lastcall = 0;
|
||||||
|
|
||||||
// find a 16MB large empty address space
|
// find a 16MB large empty address space
|
||||||
if (f->forced_cto >= 0 && f->forced_cto <= 255)
|
|
||||||
cto8 = (unsigned char) f->forced_cto;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
unsigned char buf[256];
|
unsigned char buf[256];
|
||||||
memset(buf,0,256);
|
memset(buf,0,256);
|
||||||
|
|
||||||
#if 1
|
|
||||||
for (ic = 0; ic < size - 5; ic++)
|
for (ic = 0; ic < size - 5; ic++)
|
||||||
if (COND(b,ic) && get_le32(b+ic+1)+ic+1 >= size)
|
if (COND(b,ic) && get_le32(b+ic+1)+ic+1 >= size)
|
||||||
{
|
{
|
||||||
buf[b[ic+1]] |= 1;
|
buf[b[ic+1]] |= 1;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
{
|
|
||||||
int i = size - 6;
|
|
||||||
do {
|
|
||||||
if (COND(b,i) && get_le32(b+i+1)+i+1 >= size)
|
|
||||||
buf[b[i+1]] |= 1;
|
|
||||||
} while (--i >= 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ic = 256;
|
if (getcto(f, buf) < 0)
|
||||||
if (f->preferred_ctos)
|
|
||||||
{
|
|
||||||
for (const int *pc = f->preferred_ctos; *pc >= 0; pc++)
|
|
||||||
{
|
|
||||||
if (buf[*pc & 255] == 0)
|
|
||||||
{
|
|
||||||
ic = *pc & 255;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
// just a test to see if certain ctos would improve compression
|
|
||||||
if (ic >= 256)
|
|
||||||
for (ic = 0; ic < 256; ic += 16)
|
|
||||||
if (buf[ic] == 0)
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
if (ic >= 256)
|
|
||||||
for (ic = 0; ic < 256; ic++)
|
|
||||||
if (buf[ic] == 0)
|
|
||||||
break;
|
|
||||||
if (ic >= 256)
|
|
||||||
//throwCantPack("call trick problem");
|
|
||||||
return -1;
|
return -1;
|
||||||
cto8 = (unsigned char) ic;
|
|
||||||
}
|
}
|
||||||
cto = (unsigned)cto8 << 24;
|
const unsigned char cto8 = f->cto;
|
||||||
|
#ifdef U
|
||||||
|
const unsigned cto = (unsigned)f->cto << 24;
|
||||||
|
#endif
|
||||||
|
|
||||||
for (ic = 0; ic < size - 5; ic++)
|
for (ic = 0; ic < size - 5; ic++)
|
||||||
{
|
{
|
||||||
@@ -145,7 +108,6 @@ static int F(Filter *f)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f->cto = cto8;
|
|
||||||
f->calls = calls;
|
f->calls = calls;
|
||||||
f->noncalls = noncalls;
|
f->noncalls = noncalls;
|
||||||
f->lastcall = lastcall;
|
f->lastcall = lastcall;
|
||||||
@@ -157,13 +119,17 @@ static int F(Filter *f)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// unfilter
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
#ifdef U
|
#ifdef U
|
||||||
static int U(Filter *f)
|
static int U(Filter *f)
|
||||||
{
|
{
|
||||||
upx_byte *b = f->buf;
|
upx_byte *b = f->buf;
|
||||||
const unsigned size5 = f->buf_len - 5;
|
const unsigned size5 = f->buf_len - 5;
|
||||||
const unsigned addvalue = f->addvalue;
|
const unsigned addvalue = f->addvalue;
|
||||||
const unsigned cto = f->cto << 24;
|
const unsigned cto = (unsigned)f->cto << 24;
|
||||||
|
|
||||||
unsigned ic, jc;
|
unsigned ic, jc;
|
||||||
|
|
||||||
@@ -186,7 +152,11 @@ static int U(Filter *f)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#undef F
|
||||||
|
#undef U
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
vi:ts=4:et
|
vi:ts=4:et:nowrap
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
/* fctl_ml3.ch -- filter CTO implementation
|
/* ctoj.h -- filter CTO implementation
|
||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
Copyright (C) 2000 John F. Reiser
|
Copyright (C) 2000-2002 John F. Reiser
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -23,13 +23,16 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
|
|
||||||
|
John F. Reiser
|
||||||
|
<jreiser@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
// filter / scan
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
static int F(Filter *f)
|
static int F(Filter *f)
|
||||||
@@ -45,64 +48,27 @@ static int F(Filter *f)
|
|||||||
const unsigned size = f->buf_len;
|
const unsigned size = f->buf_len;
|
||||||
|
|
||||||
unsigned ic, jc, kc;
|
unsigned ic, jc, kc;
|
||||||
unsigned cto;
|
|
||||||
unsigned char cto8;
|
|
||||||
unsigned calls = 0, noncalls = 0, noncalls2 = 0;
|
unsigned calls = 0, noncalls = 0, noncalls2 = 0;
|
||||||
unsigned lastnoncall = size, lastcall = 0;
|
unsigned lastnoncall = size, lastcall = 0;
|
||||||
|
|
||||||
// find a 16MB large empty address space
|
// find a 16MB large empty address space
|
||||||
if (f->forced_cto >= 0 && f->forced_cto <= 255)
|
|
||||||
cto8 = (unsigned char) f->forced_cto;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
unsigned char buf[256];
|
unsigned char buf[256];
|
||||||
memset(buf,0,256);
|
memset(buf,0,256);
|
||||||
|
|
||||||
#if 1
|
|
||||||
for (ic = 0; ic < size - 5; ic++)
|
for (ic = 0; ic < size - 5; ic++)
|
||||||
if (COND(b,ic,lastcall) && get_le32(b+ic+1)+ic+1 >= size)
|
if (COND(b,ic,lastcall) && get_le32(b+ic+1)+ic+1 >= size)
|
||||||
{
|
{
|
||||||
buf[b[ic+1]] |= 1;
|
buf[b[ic+1]] |= 1;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
{
|
|
||||||
int i = size - 6;
|
|
||||||
do {
|
|
||||||
if (COND(b,i,lastcall) && get_le32(b+i+1)+i+1 >= size)
|
|
||||||
buf[b[i+1]] |= 1;
|
|
||||||
} while (--i >= 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ic = 256;
|
if (getcto(f, buf) < 0)
|
||||||
if (f->preferred_ctos)
|
|
||||||
{
|
|
||||||
for (const int *pc = f->preferred_ctos; *pc >= 0; pc++)
|
|
||||||
{
|
|
||||||
if (buf[*pc & 255] == 0)
|
|
||||||
{
|
|
||||||
ic = *pc & 255;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
// just a test to see if certain ctos would improve compression
|
|
||||||
if (ic >= 256)
|
|
||||||
for (ic = 0; ic < 256; ic += 16)
|
|
||||||
if (buf[ic] == 0)
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
if (ic >= 256)
|
|
||||||
for (ic = 0; ic < 256; ic++)
|
|
||||||
if (buf[ic] == 0)
|
|
||||||
break;
|
|
||||||
if (ic >= 256)
|
|
||||||
//throwCantPack("call trick problem");
|
|
||||||
return -1;
|
return -1;
|
||||||
cto8 = (unsigned char) ic;
|
|
||||||
}
|
}
|
||||||
cto = (unsigned)cto8 << 24;
|
const unsigned char cto8 = f->cto;
|
||||||
|
#ifdef U
|
||||||
|
const unsigned cto = (unsigned)f->cto << 24;
|
||||||
|
#endif
|
||||||
|
|
||||||
for (ic = 0; ic < size - 5; ic++)
|
for (ic = 0; ic < size - 5; ic++)
|
||||||
{
|
{
|
||||||
@@ -146,7 +112,6 @@ static int F(Filter *f)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f->cto = cto8;
|
|
||||||
f->calls = calls;
|
f->calls = calls;
|
||||||
f->noncalls = noncalls;
|
f->noncalls = noncalls;
|
||||||
f->lastcall = lastcall;
|
f->lastcall = lastcall;
|
||||||
@@ -158,13 +123,17 @@ static int F(Filter *f)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// unfilter
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
#ifdef U
|
#ifdef U
|
||||||
static int U(Filter *f)
|
static int U(Filter *f)
|
||||||
{
|
{
|
||||||
upx_byte *b = f->buf;
|
upx_byte *b = f->buf;
|
||||||
const unsigned size5 = f->buf_len - 5;
|
const unsigned size5 = f->buf_len - 5;
|
||||||
const unsigned addvalue = f->addvalue;
|
const unsigned addvalue = f->addvalue;
|
||||||
const unsigned cto = f->cto << 24;
|
const unsigned cto = (unsigned)f->cto << 24;
|
||||||
unsigned lastcall = 0;
|
unsigned lastcall = 0;
|
||||||
|
|
||||||
unsigned ic, jc;
|
unsigned ic, jc;
|
||||||
@@ -188,7 +157,11 @@ static int U(Filter *f)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#undef F
|
||||||
|
#undef U
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
vi:ts=4:et
|
vi:ts=4:et:nowrap
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -0,0 +1,343 @@
|
|||||||
|
/* ctojr.h -- filter CTO implementation; renumber destinations MRU
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
|
Copyright (C) 2000-2002 John F. Reiser
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
|
|
||||||
|
John F. Reiser
|
||||||
|
<jreiser@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// filter / scan
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#ifdef U //{
|
||||||
|
#define NOFILT 0 // no filter
|
||||||
|
#define FNOMRU 1 // filter, but not using mru
|
||||||
|
#define MRUFLT 2 // mru filter
|
||||||
|
|
||||||
|
static unsigned
|
||||||
|
f80_call(Filter const *f)
|
||||||
|
{
|
||||||
|
return (1+ (0x0f & f->id)) % 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned
|
||||||
|
f80_jmp1(Filter const *f)
|
||||||
|
{
|
||||||
|
return ((1+ (0x0f & f->id)) / 3) % 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned
|
||||||
|
f80_jcc2(Filter const *f)
|
||||||
|
{
|
||||||
|
return f80_jmp1(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int const N_MRU = 32; // does not have to be a power of 2
|
||||||
|
|
||||||
|
// Adaptively remember recent destinations.
|
||||||
|
static void
|
||||||
|
update_mru(
|
||||||
|
unsigned const jc, // destination address
|
||||||
|
int const kh, // mru[kh] is slot where found
|
||||||
|
unsigned mru[N_MRU], // circular buffer of most recent destinations
|
||||||
|
int &hand, // mru[hand] is most recent destination
|
||||||
|
int &tail // mru[tail] is beyond oldest destination ("cold cache" startup)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (0 > --hand) {
|
||||||
|
hand = N_MRU -1;
|
||||||
|
}
|
||||||
|
unsigned const t = mru[hand]; // entry which will be overwritten by jc
|
||||||
|
if (0!=t) { // have seen at least N_MRU destinations
|
||||||
|
mru[kh] = t;
|
||||||
|
}
|
||||||
|
else { // "cold cache": keep active region contiguous
|
||||||
|
if (0 > --tail) {
|
||||||
|
tail = N_MRU -1;
|
||||||
|
}
|
||||||
|
unsigned const t2 = mru[tail];
|
||||||
|
mru[tail] = 0;
|
||||||
|
mru[kh] = t2;
|
||||||
|
}
|
||||||
|
mru[hand] = jc;
|
||||||
|
}
|
||||||
|
#endif //}
|
||||||
|
|
||||||
|
|
||||||
|
static int F(Filter *f)
|
||||||
|
{
|
||||||
|
#ifdef U
|
||||||
|
// filter
|
||||||
|
upx_byte *const b = f->buf;
|
||||||
|
#else
|
||||||
|
// scan
|
||||||
|
const upx_byte *b = f->buf;
|
||||||
|
#endif
|
||||||
|
const unsigned size = f->buf_len;
|
||||||
|
|
||||||
|
unsigned ic, jc, kc;
|
||||||
|
unsigned calls = 0, noncalls = 0, noncalls2 = 0;
|
||||||
|
unsigned lastnoncall = size, lastcall = 0;
|
||||||
|
unsigned wtally[3]; memset(wtally, 0, sizeof(wtally));
|
||||||
|
|
||||||
|
#ifdef U //{
|
||||||
|
unsigned const f_call = f80_call(f);
|
||||||
|
unsigned const f_jmp1 = f80_jmp1(f);
|
||||||
|
unsigned const f_jcc2 = f80_jcc2(f);
|
||||||
|
|
||||||
|
int hand = 0, tail = 0;
|
||||||
|
unsigned mru[N_MRU];
|
||||||
|
memset(&mru[0], 0, sizeof(mru));
|
||||||
|
assert(N_MRU<=256);
|
||||||
|
f->n_mru = (MRUFLT==f_call || MRUFLT==f_jmp1 || MRUFLT==f_jcc2) ?
|
||||||
|
N_MRU : 0;
|
||||||
|
#endif //}
|
||||||
|
|
||||||
|
// FIXME: We must fit into 8MB because we steal one bit.
|
||||||
|
// find a 16MB large empty address space
|
||||||
|
{
|
||||||
|
int which;
|
||||||
|
unsigned char buf[256];
|
||||||
|
memset(buf,0,256);
|
||||||
|
|
||||||
|
for (ic = 0; ic < size - 5; ic++)
|
||||||
|
if (CONDF(which,b,ic,lastcall) && get_le32(b+ic+1)+ic+1 >= size)
|
||||||
|
{
|
||||||
|
buf[b[ic+1]] |= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getcto(f, buf) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
const unsigned char cto8 = f->cto;
|
||||||
|
#ifdef U
|
||||||
|
const unsigned cto = (unsigned)f->cto << 24;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (ic = 0; ic < size - 5; ic++)
|
||||||
|
{
|
||||||
|
int which;
|
||||||
|
int f_on = 0;
|
||||||
|
if (!CONDF(which,b,ic,lastcall))
|
||||||
|
continue;
|
||||||
|
++wtally[which];
|
||||||
|
jc = get_le32(b+ic+1)+ic+1;
|
||||||
|
// try to detect 'real' calls only
|
||||||
|
if (jc < size)
|
||||||
|
{
|
||||||
|
#ifdef U
|
||||||
|
if (2==which && NOFILT!=f_jcc2) { // 6-byte Jcc <disp32>
|
||||||
|
// Prefix 0x0f is constant, but opcode condition 0x80..0x8f
|
||||||
|
// varies. Because we store the destination (or its mru index)
|
||||||
|
// in be32 big endian format, the low-addressed bytes
|
||||||
|
// will tend to be constant. Swap prefix and opcode
|
||||||
|
// so that constants are together for better compression.
|
||||||
|
unsigned char const t =
|
||||||
|
b[ic-1];
|
||||||
|
b[ic-1] = b[ic];
|
||||||
|
b[ic] = t;
|
||||||
|
}
|
||||||
|
// FIXME [?]: Extend to 8 bytes if "ADD ESP, byte 4*n" follows CALL.
|
||||||
|
// This will require two related cto's (consecutive, or otherwise).
|
||||||
|
if ((0==which && MRUFLT==f_call)
|
||||||
|
|| (1==which && MRUFLT==f_jmp1)
|
||||||
|
|| (2==which && MRUFLT==f_jcc2) ) {
|
||||||
|
f_on = 1;
|
||||||
|
// Recode the destination: narrower mru indices
|
||||||
|
// should compress better than wider addresses.
|
||||||
|
// (But not when offset of match is unlimited?)
|
||||||
|
int k;
|
||||||
|
for (k = 0; k < N_MRU; ++k) {
|
||||||
|
int kh = hand + k;
|
||||||
|
if (N_MRU <= kh) {
|
||||||
|
kh -= N_MRU;
|
||||||
|
}
|
||||||
|
if (mru[kh] == jc) { // destination was seen recently
|
||||||
|
set_be32(b+ic+1,((k<<1)|0)+cto);
|
||||||
|
update_mru(jc, kh, mru, hand, tail);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (k == N_MRU) { // loop failed; jc is not in mru[]
|
||||||
|
set_be32(b+ic+1,((jc<<1)|1)+cto);
|
||||||
|
// Adaptively remember recent destinations.
|
||||||
|
if (0 > --hand) {
|
||||||
|
hand = N_MRU -1;
|
||||||
|
}
|
||||||
|
mru[hand] = jc;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
if ((0==which && NOFILT!=f_call)
|
||||||
|
|| (1==which && NOFILT!=f_jmp1)
|
||||||
|
|| (2==which && NOFILT!=f_jcc2) ) {
|
||||||
|
f_on = 1;
|
||||||
|
set_be32(b+ic+1, jc+cto);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (f_on) {
|
||||||
|
if (ic - lastnoncall < 5)
|
||||||
|
{
|
||||||
|
// check the last 4 bytes before this call
|
||||||
|
for (kc = 4; kc; kc--)
|
||||||
|
if (CONDF(which,b,ic-kc,lastcall) && b[ic-kc+1] == cto8)
|
||||||
|
break;
|
||||||
|
if (kc)
|
||||||
|
{
|
||||||
|
#ifdef U
|
||||||
|
// restore original
|
||||||
|
if (2==which) {
|
||||||
|
// Unswap prefix and opcode for 6-byte Jcc <disp32>
|
||||||
|
unsigned char const t =
|
||||||
|
b[ic-1];
|
||||||
|
b[ic-1] = b[ic];
|
||||||
|
b[ic] = t;
|
||||||
|
}
|
||||||
|
set_le32(b+ic+1,jc-ic-1);
|
||||||
|
#endif
|
||||||
|
if (b[ic+1] == cto8)
|
||||||
|
return 1; // fail - buffer not restored
|
||||||
|
lastnoncall = ic;
|
||||||
|
noncalls2++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
calls++;
|
||||||
|
ic += 4;
|
||||||
|
lastcall = ic+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(b[ic+1] != cto8); // this should not happen
|
||||||
|
lastnoncall = ic;
|
||||||
|
noncalls++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
f->calls = calls;
|
||||||
|
f->noncalls = noncalls;
|
||||||
|
f->lastcall = lastcall;
|
||||||
|
|
||||||
|
/*#ifdef TESTING*/
|
||||||
|
printf("\ncalls=%d noncalls=%d noncalls2=%d text_size=%x calltrickoffset=%x\n",
|
||||||
|
calls,noncalls,noncalls2,size,cto8);
|
||||||
|
printf("CALL/JMP/JCC %d %d %d\n",wtally[0],wtally[1],wtally[2]);
|
||||||
|
/*#endif*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// unfilter
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#ifdef U
|
||||||
|
static int U(Filter *f)
|
||||||
|
{
|
||||||
|
unsigned ic, jc;
|
||||||
|
|
||||||
|
upx_byte *const b = f->buf;
|
||||||
|
const unsigned size5 = f->buf_len - 5;
|
||||||
|
const unsigned cto = (unsigned)f->cto << 24;
|
||||||
|
unsigned lastcall = 0;
|
||||||
|
int hand = 0, tail = 0;
|
||||||
|
unsigned const f_call = f80_call(f);
|
||||||
|
unsigned const f_jmp1 = f80_jmp1(f);
|
||||||
|
unsigned const f_jcc2 = f80_jcc2(f);
|
||||||
|
|
||||||
|
unsigned mru[N_MRU];
|
||||||
|
memset(&mru[0], 0, sizeof(mru));
|
||||||
|
|
||||||
|
for (ic = 0; ic < size5; ic++) {
|
||||||
|
int which;
|
||||||
|
if (CONDU(which,b,ic,lastcall))
|
||||||
|
{
|
||||||
|
unsigned f_on = 0;
|
||||||
|
jc = get_be32(b+ic+1) - cto;
|
||||||
|
if (b[ic+1] == f->cto)
|
||||||
|
{
|
||||||
|
if ((0==which && MRUFLT==f_call)
|
||||||
|
|| (1==which && MRUFLT==f_jmp1)
|
||||||
|
|| (2==which && MRUFLT==f_jcc2) ) {
|
||||||
|
f_on = 1;
|
||||||
|
if (1&jc) { // 1st time at this destination
|
||||||
|
jc >>= 1;
|
||||||
|
if (0 > --hand) {
|
||||||
|
hand = N_MRU -1;
|
||||||
|
}
|
||||||
|
mru[hand] = jc;
|
||||||
|
}
|
||||||
|
else { // not 1st time at this destination
|
||||||
|
jc >>= 1;
|
||||||
|
int kh = jc + hand;
|
||||||
|
if (N_MRU <= kh) {
|
||||||
|
kh -= N_MRU;
|
||||||
|
}
|
||||||
|
jc = mru[kh];
|
||||||
|
update_mru(jc, kh, mru, hand, tail);
|
||||||
|
}
|
||||||
|
set_le32(b+ic+1,jc-ic-1);
|
||||||
|
} else
|
||||||
|
if ((0==which && NOFILT!=f_call)
|
||||||
|
|| (1==which && NOFILT!=f_jmp1)
|
||||||
|
|| (2==which && NOFILT!=f_jcc2) ) {
|
||||||
|
f_on = 1;
|
||||||
|
set_le32(b+ic+1,jc-ic-1);
|
||||||
|
}
|
||||||
|
if (2==which && NOFILT!=f_jcc2) {
|
||||||
|
// Unswap prefix and opcode for 6-byte Jcc <disp32>
|
||||||
|
unsigned char const t =
|
||||||
|
b[ic-1];
|
||||||
|
b[ic-1] = b[ic];
|
||||||
|
b[ic] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f_on) {
|
||||||
|
f->calls++;
|
||||||
|
ic += 4;
|
||||||
|
f->lastcall = lastcall = ic+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
f->noncalls++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#undef F
|
||||||
|
#undef U
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
vi:ts=4:et:nowrap
|
||||||
|
*/
|
||||||
|
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
/* ctok.h -- filter CTO implementation
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
|
Copyright (C) 2000-2002 John F. Reiser
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
|
|
||||||
|
John F. Reiser
|
||||||
|
<jreiser@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// filter / scan
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
static int F(Filter *f)
|
||||||
|
{
|
||||||
|
#ifdef U
|
||||||
|
// filter
|
||||||
|
upx_byte *b = f->buf;
|
||||||
|
const unsigned addvalue = f->addvalue;
|
||||||
|
#else
|
||||||
|
// scan
|
||||||
|
const upx_byte *b = f->buf;
|
||||||
|
#endif
|
||||||
|
const unsigned size = f->buf_len;
|
||||||
|
unsigned const id = f->id;
|
||||||
|
|
||||||
|
unsigned ic, jc, kc;
|
||||||
|
unsigned calls = 0, noncalls = 0, noncalls2 = 0;
|
||||||
|
unsigned lastnoncall = size, lastcall = 0;
|
||||||
|
|
||||||
|
// find a 16MB large empty address space
|
||||||
|
{
|
||||||
|
unsigned char buf[256];
|
||||||
|
memset(buf,0,256);
|
||||||
|
|
||||||
|
for (ic = 0; ic < size - 5; ic++)
|
||||||
|
if (COND(b,ic,lastcall,id) && get_le32(b+ic+1)+ic+1 >= size)
|
||||||
|
{
|
||||||
|
buf[b[ic+1]] |= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getcto(f, buf) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
const unsigned char cto8 = f->cto;
|
||||||
|
#ifdef U
|
||||||
|
const unsigned cto = (unsigned)f->cto << 24;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (ic = 0; ic < size - 5; ic++)
|
||||||
|
{
|
||||||
|
if (!COND(b,ic,lastcall,id))
|
||||||
|
continue;
|
||||||
|
jc = get_le32(b+ic+1)+ic+1;
|
||||||
|
// try to detect 'real' calls only
|
||||||
|
if (jc < size)
|
||||||
|
{
|
||||||
|
#ifdef U
|
||||||
|
set_be32(b+ic+1,jc+addvalue+cto);
|
||||||
|
#endif
|
||||||
|
if (ic - lastnoncall < 5)
|
||||||
|
{
|
||||||
|
// check the last 4 bytes before this call
|
||||||
|
for (kc = 4; kc; kc--)
|
||||||
|
if (COND(b,ic-kc,lastcall,id) && b[ic-kc+1] == cto8)
|
||||||
|
break;
|
||||||
|
if (kc)
|
||||||
|
{
|
||||||
|
#ifdef U
|
||||||
|
// restore original
|
||||||
|
set_le32(b+ic+1,jc-ic-1);
|
||||||
|
#endif
|
||||||
|
if (b[ic+1] == cto8)
|
||||||
|
return 1; // fail - buffer not restored
|
||||||
|
lastnoncall = ic;
|
||||||
|
noncalls2++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
calls++;
|
||||||
|
ic += 4;
|
||||||
|
lastcall = ic+1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(b[ic+1] != cto8); // this should not happen
|
||||||
|
lastnoncall = ic;
|
||||||
|
noncalls++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
f->calls = calls;
|
||||||
|
f->noncalls = noncalls;
|
||||||
|
f->lastcall = lastcall;
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
printf("\ncalls=%d noncalls=%d noncalls2=%d text_size=%x calltrickoffset=%x\n",calls,noncalls,noncalls2,size,cto);
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// unfilter
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#ifdef U
|
||||||
|
static int U(Filter *f)
|
||||||
|
{
|
||||||
|
upx_byte *b = f->buf;
|
||||||
|
const unsigned size5 = f->buf_len - 5;
|
||||||
|
const unsigned addvalue = f->addvalue;
|
||||||
|
const unsigned cto = (unsigned)f->cto << 24;
|
||||||
|
unsigned const id = f->id;
|
||||||
|
unsigned lastcall = 0;
|
||||||
|
|
||||||
|
unsigned ic, jc;
|
||||||
|
|
||||||
|
for (ic = 0; ic < size5; ic++)
|
||||||
|
if (COND(b,ic,lastcall,id))
|
||||||
|
{
|
||||||
|
jc = get_be32(b+ic+1);
|
||||||
|
if (b[ic+1] == f->cto)
|
||||||
|
{
|
||||||
|
set_le32(b+ic+1,jc-ic-1-addvalue-cto);
|
||||||
|
f->calls++;
|
||||||
|
ic += 4;
|
||||||
|
f->lastcall = lastcall = ic+1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
f->noncalls++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#undef F
|
||||||
|
#undef U
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
vi:ts=4:et:nowrap
|
||||||
|
*/
|
||||||
|
|
||||||
@@ -0,0 +1,173 @@
|
|||||||
|
/* ctsw.h -- call-/swaptrick filter
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// 16-bit call-/swaptrick ("naive")
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#define CTSW16(f, cond1, cond2, addvalue, get, set) \
|
||||||
|
upx_byte *b = f->buf; \
|
||||||
|
upx_byte *b_end = b + f->buf_len - 3; \
|
||||||
|
do { \
|
||||||
|
if (cond1) \
|
||||||
|
{ \
|
||||||
|
b += 1; \
|
||||||
|
unsigned a = (unsigned) (b - f->buf); \
|
||||||
|
f->lastcall = a; \
|
||||||
|
set(b, get(b) + (addvalue)); \
|
||||||
|
f->calls++; \
|
||||||
|
b += 2 - 1; \
|
||||||
|
} \
|
||||||
|
else if (cond2) \
|
||||||
|
{ \
|
||||||
|
b += 1; \
|
||||||
|
unsigned a = (unsigned) (b - f->buf); \
|
||||||
|
f->lastcall = a; \
|
||||||
|
set(b, get(b)); \
|
||||||
|
f->calls++; \
|
||||||
|
b += 2 - 1; \
|
||||||
|
} \
|
||||||
|
} while (++b < b_end); \
|
||||||
|
if (f->lastcall) f->lastcall += 2; \
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
|
// filter
|
||||||
|
static int f_ctsw16_e8_e9(Filter *f)
|
||||||
|
{
|
||||||
|
CTSW16(f, (*b == 0xe8), (*b == 0xe9), a + f->addvalue, get_le16, set_be16)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_ctsw16_e9_e8(Filter *f)
|
||||||
|
{
|
||||||
|
CTSW16(f, (*b == 0xe9), (*b == 0xe8), a + f->addvalue, get_le16, set_be16)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// unfilter
|
||||||
|
static int u_ctsw16_e8_e9(Filter *f)
|
||||||
|
{
|
||||||
|
CTSW16(f, (*b == 0xe8), (*b == 0xe9), 0 - a - f->addvalue, get_be16, set_le16)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_ctsw16_e9_e8(Filter *f)
|
||||||
|
{
|
||||||
|
CTSW16(f, (*b == 0xe9), (*b == 0xe8), 0 - a - f->addvalue, get_be16, set_le16)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// scan
|
||||||
|
static int s_ctsw16_e8_e9(Filter *f)
|
||||||
|
{
|
||||||
|
CTSW16(f, (*b == 0xe8), (*b == 0xe9), a + f->addvalue, get_le16, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_ctsw16_e9_e8(Filter *f)
|
||||||
|
{
|
||||||
|
CTSW16(f, (*b == 0xe9), (*b == 0xe8), a + f->addvalue, get_le16, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#undef CTSW16
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// 32-bit call-/swaptrick ("naive")
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#define CTSW32(f, cond1, cond2, addvalue, get, set) \
|
||||||
|
upx_byte *b = f->buf; \
|
||||||
|
upx_byte *b_end = b + f->buf_len - 5; \
|
||||||
|
do { \
|
||||||
|
if (cond1) \
|
||||||
|
{ \
|
||||||
|
b += 1; \
|
||||||
|
unsigned a = (unsigned) (b - f->buf); \
|
||||||
|
f->lastcall = a; \
|
||||||
|
set(b, get(b) + (addvalue)); \
|
||||||
|
f->calls++; \
|
||||||
|
b += 4 - 1; \
|
||||||
|
} \
|
||||||
|
else if (cond2) \
|
||||||
|
{ \
|
||||||
|
b += 1; \
|
||||||
|
unsigned a = (unsigned) (b - f->buf); \
|
||||||
|
f->lastcall = a; \
|
||||||
|
set(b, get(b)); \
|
||||||
|
f->calls++; \
|
||||||
|
b += 4 - 1; \
|
||||||
|
} \
|
||||||
|
} while (++b < b_end); \
|
||||||
|
if (f->lastcall) f->lastcall += 4; \
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
|
// filter
|
||||||
|
static int f_ctsw32_e8_e9(Filter *f)
|
||||||
|
{
|
||||||
|
CTSW32(f, (*b == 0xe8), (*b == 0xe9), a + f->addvalue, get_le32, set_be32)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_ctsw32_e9_e8(Filter *f)
|
||||||
|
{
|
||||||
|
CTSW32(f, (*b == 0xe9), (*b == 0xe8), a + f->addvalue, get_le32, set_be32)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// unfilter
|
||||||
|
static int u_ctsw32_e8_e9(Filter *f)
|
||||||
|
{
|
||||||
|
CTSW32(f, (*b == 0xe8), (*b == 0xe9), 0 - a - f->addvalue, get_be32, set_le32)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_ctsw32_e9_e8(Filter *f)
|
||||||
|
{
|
||||||
|
CTSW32(f, (*b == 0xe9), (*b == 0xe8), 0 - a - f->addvalue, get_be32, set_le32)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// scan
|
||||||
|
static int s_ctsw32_e8_e9(Filter *f)
|
||||||
|
{
|
||||||
|
CTSW32(f, (*b == 0xe8), (*b == 0xe9), a + f->addvalue, get_le32, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_ctsw32_e9_e8(Filter *f)
|
||||||
|
{
|
||||||
|
CTSW32(f, (*b == 0xe9), (*b == 0xe8), a + f->addvalue, get_le32, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#undef CTSW32
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
vi:ts=4:et:nowrap
|
||||||
|
*/
|
||||||
|
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
/* getcto.h -- calltrick util
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
static int getcto(Filter *f, const unsigned char *buf, const int n=256)
|
||||||
|
{
|
||||||
|
int ic = n;
|
||||||
|
|
||||||
|
if (f->preferred_ctos)
|
||||||
|
{
|
||||||
|
for (const int *pc = f->preferred_ctos; *pc >= 0; pc++)
|
||||||
|
{
|
||||||
|
if (*pc < n && buf[*pc] == 0)
|
||||||
|
{
|
||||||
|
ic = *pc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// just a test to see if certain ctos would improve compression
|
||||||
|
if (ic >= n)
|
||||||
|
for (ic = 0; ic < n; ic += 16)
|
||||||
|
if (buf[ic] == 0)
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
if (ic >= n)
|
||||||
|
for (ic = 0; ic < n; ic++)
|
||||||
|
if (buf[ic] == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (ic >= n)
|
||||||
|
//throwCantPack("call trick problem");
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
f->cto = (unsigned char) ic;
|
||||||
|
return ic;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
vi:ts=4:et:nowrap
|
||||||
|
*/
|
||||||
|
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
/* sub.hh -- simple delta filter
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#define SUB(f, N, T, get, set) \
|
||||||
|
upx_byte *b = f->buf; \
|
||||||
|
unsigned l = f->buf_len / sizeof(T); \
|
||||||
|
int i; \
|
||||||
|
T d[N]; \
|
||||||
|
\
|
||||||
|
i = N - 1; do d[i] = 0; while (--i >= 0); \
|
||||||
|
\
|
||||||
|
i = N - 1; \
|
||||||
|
do { \
|
||||||
|
T delta = (T) (get(b) - d[i]); \
|
||||||
|
set(b, delta); \
|
||||||
|
d[i] = (T) (d[i] + delta); \
|
||||||
|
b += sizeof(T); \
|
||||||
|
if (--i < 0) \
|
||||||
|
i = N - 1; \
|
||||||
|
} while (--l > 0); \
|
||||||
|
f->calls = (f->buf_len / sizeof(T)) - N; \
|
||||||
|
assert((int)f->calls > 0); \
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
|
#define ADD(f, N, T, get, set) \
|
||||||
|
upx_byte *b = f->buf; \
|
||||||
|
unsigned l = f->buf_len / sizeof(T); \
|
||||||
|
int i; \
|
||||||
|
T d[N]; \
|
||||||
|
\
|
||||||
|
i = N - 1; do d[i] = 0; while (--i >= 0); \
|
||||||
|
\
|
||||||
|
i = N - 1; \
|
||||||
|
do { \
|
||||||
|
d[i] = (T) (d[i] + get(b)); \
|
||||||
|
set(b, d[i]); \
|
||||||
|
b += sizeof(T); \
|
||||||
|
if (--i < 0) \
|
||||||
|
i = N - 1; \
|
||||||
|
} while (--l > 0); \
|
||||||
|
f->calls = (f->buf_len / sizeof(T)) - N; \
|
||||||
|
assert((int)f->calls > 0); \
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
|
#define SCAN(f, N, T, get, set) \
|
||||||
|
f->calls = (f->buf_len / sizeof(T)) - N; \
|
||||||
|
assert((int)f->calls > 0); \
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
vi:ts=4:et:nowrap
|
||||||
|
*/
|
||||||
|
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
/* sub16.h -- simple delta filter
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include "sub.hh"
|
||||||
|
|
||||||
|
#define SUB16(f, N) SUB(f, N, unsigned short, get_le16, set_le16)
|
||||||
|
#define ADD16(f, N) ADD(f, N, unsigned short, get_le16, set_le16)
|
||||||
|
#define SCAN16(f, N) SCAN(f, N, unsigned short, get_le16, set_le16)
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
// filter
|
||||||
|
static int f_sub16_1(Filter *f)
|
||||||
|
{
|
||||||
|
SUB16(f, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_sub16_2(Filter *f)
|
||||||
|
{
|
||||||
|
SUB16(f, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_sub16_3(Filter *f)
|
||||||
|
{
|
||||||
|
SUB16(f, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_sub16_4(Filter *f)
|
||||||
|
{
|
||||||
|
SUB16(f, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// unfilter
|
||||||
|
static int u_sub16_1(Filter *f)
|
||||||
|
{
|
||||||
|
ADD16(f, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_sub16_2(Filter *f)
|
||||||
|
{
|
||||||
|
ADD16(f, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_sub16_3(Filter *f)
|
||||||
|
{
|
||||||
|
ADD16(f, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_sub16_4(Filter *f)
|
||||||
|
{
|
||||||
|
ADD16(f, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// scan
|
||||||
|
static int s_sub16_1(Filter *f)
|
||||||
|
{
|
||||||
|
SCAN16(f, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_sub16_2(Filter *f)
|
||||||
|
{
|
||||||
|
SCAN16(f, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_sub16_3(Filter *f)
|
||||||
|
{
|
||||||
|
SCAN16(f, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_sub16_4(Filter *f)
|
||||||
|
{
|
||||||
|
SCAN16(f, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#undef SUB
|
||||||
|
#undef ADD
|
||||||
|
#undef SCAN
|
||||||
|
#undef SUB16
|
||||||
|
#undef ADD16
|
||||||
|
#undef SCAN16
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
vi:ts=4:et:nowrap
|
||||||
|
*/
|
||||||
|
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
/* sub32.h -- simple delta filter
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include "sub.hh"
|
||||||
|
|
||||||
|
#define SUB32(f, N) SUB(f, N, unsigned int, get_le32, set_le32)
|
||||||
|
#define ADD32(f, N) ADD(f, N, unsigned int, get_le32, set_le32)
|
||||||
|
#define SCAN32(f, N) SCAN(f, N, unsigned int, get_le32, set_le32)
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
// filter
|
||||||
|
static int f_sub32_1(Filter *f)
|
||||||
|
{
|
||||||
|
SUB32(f, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_sub32_2(Filter *f)
|
||||||
|
{
|
||||||
|
SUB32(f, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_sub32_3(Filter *f)
|
||||||
|
{
|
||||||
|
SUB32(f, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_sub32_4(Filter *f)
|
||||||
|
{
|
||||||
|
SUB32(f, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// unfilter
|
||||||
|
static int u_sub32_1(Filter *f)
|
||||||
|
{
|
||||||
|
ADD32(f, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_sub32_2(Filter *f)
|
||||||
|
{
|
||||||
|
ADD32(f, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_sub32_3(Filter *f)
|
||||||
|
{
|
||||||
|
ADD32(f, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_sub32_4(Filter *f)
|
||||||
|
{
|
||||||
|
ADD32(f, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// scan
|
||||||
|
static int s_sub32_1(Filter *f)
|
||||||
|
{
|
||||||
|
SCAN32(f, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_sub32_2(Filter *f)
|
||||||
|
{
|
||||||
|
SCAN32(f, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_sub32_3(Filter *f)
|
||||||
|
{
|
||||||
|
SCAN32(f, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_sub32_4(Filter *f)
|
||||||
|
{
|
||||||
|
SCAN32(f, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#undef SUB
|
||||||
|
#undef ADD
|
||||||
|
#undef SCAN
|
||||||
|
#undef SUB32
|
||||||
|
#undef ADD32
|
||||||
|
#undef SCAN32
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
vi:ts=4:et:nowrap
|
||||||
|
*/
|
||||||
|
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
/* sub8.h -- simple delta filter
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include "sub.hh"
|
||||||
|
|
||||||
|
#define SUB8(f, N) SUB(f, N, unsigned char, get_8, set_8)
|
||||||
|
#define ADD8(f, N) ADD(f, N, unsigned char, get_8, set_8)
|
||||||
|
#define SCAN8(f, N) SCAN(f, N, unsigned char, get_8, set_8)
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
// filter
|
||||||
|
static int f_sub8_1(Filter *f)
|
||||||
|
{
|
||||||
|
SUB8(f, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_sub8_2(Filter *f)
|
||||||
|
{
|
||||||
|
SUB8(f, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_sub8_3(Filter *f)
|
||||||
|
{
|
||||||
|
SUB8(f, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_sub8_4(Filter *f)
|
||||||
|
{
|
||||||
|
SUB8(f, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// unfilter
|
||||||
|
static int u_sub8_1(Filter *f)
|
||||||
|
{
|
||||||
|
ADD8(f, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_sub8_2(Filter *f)
|
||||||
|
{
|
||||||
|
ADD8(f, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_sub8_3(Filter *f)
|
||||||
|
{
|
||||||
|
ADD8(f, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_sub8_4(Filter *f)
|
||||||
|
{
|
||||||
|
ADD8(f, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// scan
|
||||||
|
static int s_sub8_1(Filter *f)
|
||||||
|
{
|
||||||
|
SCAN8(f, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_sub8_2(Filter *f)
|
||||||
|
{
|
||||||
|
SCAN8(f, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_sub8_3(Filter *f)
|
||||||
|
{
|
||||||
|
SCAN8(f, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_sub8_4(Filter *f)
|
||||||
|
{
|
||||||
|
SCAN8(f, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#undef SUB
|
||||||
|
#undef ADD
|
||||||
|
#undef SCAN
|
||||||
|
#undef SUB8
|
||||||
|
#undef ADD8
|
||||||
|
#undef SCAN8
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
vi:ts=4:et:nowrap
|
||||||
|
*/
|
||||||
|
|
||||||
+188
@@ -0,0 +1,188 @@
|
|||||||
|
/* sw.h -- swaptrick filter
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// 16-bit swaptrick ("naive")
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#define SW16(f, cond, get, set) \
|
||||||
|
upx_byte *b = f->buf; \
|
||||||
|
upx_byte *b_end = b + f->buf_len - 3; \
|
||||||
|
do { \
|
||||||
|
if (cond) \
|
||||||
|
{ \
|
||||||
|
b += 1; \
|
||||||
|
unsigned a = (unsigned) (b - f->buf); \
|
||||||
|
f->lastcall = a; \
|
||||||
|
set(b, get(b)); \
|
||||||
|
f->calls++; \
|
||||||
|
b += 2 - 1; \
|
||||||
|
} \
|
||||||
|
} while (++b < b_end); \
|
||||||
|
if (f->lastcall) f->lastcall += 2; \
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
|
// filter
|
||||||
|
static int f_sw16_e8(Filter *f)
|
||||||
|
{
|
||||||
|
SW16(f, (*b == 0xe8), get_le16, set_be16)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_sw16_e9(Filter *f)
|
||||||
|
{
|
||||||
|
SW16(f, (*b == 0xe9), get_le16, set_be16)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_sw16_e8e9(Filter *f)
|
||||||
|
{
|
||||||
|
SW16(f, (*b == 0xe8 || *b == 0xe9), get_le16, set_be16)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// unfilter
|
||||||
|
static int u_sw16_e8(Filter *f)
|
||||||
|
{
|
||||||
|
SW16(f, (*b == 0xe8), get_be16, set_le16)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_sw16_e9(Filter *f)
|
||||||
|
{
|
||||||
|
SW16(f, (*b == 0xe9), get_be16, set_le16)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_sw16_e8e9(Filter *f)
|
||||||
|
{
|
||||||
|
SW16(f, (*b == 0xe8 || *b == 0xe9), get_be16, set_le16)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// scan
|
||||||
|
static int s_sw16_e8(Filter *f)
|
||||||
|
{
|
||||||
|
SW16(f, (*b == 0xe8), get_le16, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_sw16_e9(Filter *f)
|
||||||
|
{
|
||||||
|
SW16(f, (*b == 0xe9), get_le16, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_sw16_e8e9(Filter *f)
|
||||||
|
{
|
||||||
|
SW16(f, (*b == 0xe8 || *b == 0xe9), get_le16, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#undef SW16
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// 32-bit swaptrick ("naive")
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#define SW32(f, cond, get, set) \
|
||||||
|
upx_byte *b = f->buf; \
|
||||||
|
upx_byte *b_end = b + f->buf_len - 5; \
|
||||||
|
do { \
|
||||||
|
if (cond) \
|
||||||
|
{ \
|
||||||
|
b += 1; \
|
||||||
|
unsigned a = (unsigned) (b - f->buf); \
|
||||||
|
f->lastcall = a; \
|
||||||
|
set(b, get(b)); \
|
||||||
|
f->calls++; \
|
||||||
|
b += 4 - 1; \
|
||||||
|
} \
|
||||||
|
} while (++b < b_end); \
|
||||||
|
if (f->lastcall) f->lastcall += 4; \
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
|
// filter
|
||||||
|
static int f_sw32_e8(Filter *f)
|
||||||
|
{
|
||||||
|
SW32(f, (*b == 0xe8), get_le32, set_be32)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_sw32_e9(Filter *f)
|
||||||
|
{
|
||||||
|
SW32(f, (*b == 0xe9), get_le32, set_be32)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_sw32_e8e9(Filter *f)
|
||||||
|
{
|
||||||
|
SW32(f, (*b == 0xe8 || *b == 0xe9), get_le32, set_be32)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// unfilter
|
||||||
|
static int u_sw32_e8(Filter *f)
|
||||||
|
{
|
||||||
|
SW32(f, (*b == 0xe8), get_be32, set_le32)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_sw32_e9(Filter *f)
|
||||||
|
{
|
||||||
|
SW32(f, (*b == 0xe9), get_be32, set_le32)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int u_sw32_e8e9(Filter *f)
|
||||||
|
{
|
||||||
|
SW32(f, (*b == 0xe8 || *b == 0xe9), get_be32, set_le32)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// scan
|
||||||
|
static int s_sw32_e8(Filter *f)
|
||||||
|
{
|
||||||
|
SW32(f, (*b == 0xe8), get_le32, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_sw32_e9(Filter *f)
|
||||||
|
{
|
||||||
|
SW32(f, (*b == 0xe9), get_le32, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_sw32_e8e9(Filter *f)
|
||||||
|
{
|
||||||
|
SW32(f, (*b == 0xe8 || *b == 0xe9), get_le32, set_dummy)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#undef SW32
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
vi:ts=4:et:nowrap
|
||||||
|
*/
|
||||||
|
|
||||||
+154
-365
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -31,375 +31,118 @@
|
|||||||
|
|
||||||
|
|
||||||
#define set_dummy(p, v) ((void)0)
|
#define set_dummy(p, v) ((void)0)
|
||||||
|
#define get_8(p) (*(p))
|
||||||
|
#define set_8(p, v) (*(p) = (v))
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// 16-bit calltrick ("naive")
|
// util
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#define CT16(f, cond, addvalue, get, set) \
|
#include "filter/getcto.h"
|
||||||
upx_byte *b = f->buf; \
|
|
||||||
upx_byte *b_end = b + f->buf_len - 3; \
|
|
||||||
do { \
|
|
||||||
if (cond) \
|
|
||||||
{ \
|
|
||||||
b += 1; \
|
|
||||||
unsigned a = (unsigned) (b - f->buf); \
|
|
||||||
f->lastcall = a; \
|
|
||||||
set(b, get(b) + (addvalue)); \
|
|
||||||
f->calls++; \
|
|
||||||
b += 2 - 1; \
|
|
||||||
} \
|
|
||||||
} while (++b < b_end); \
|
|
||||||
if (f->lastcall) f->lastcall += 2; \
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// filter: e8, e9, e8e9
|
|
||||||
static int f_ct16_e8(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe8), a + f->addvalue, get_le16, set_le16)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int f_ct16_e9(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe9), a + f->addvalue, get_le16, set_le16)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int f_ct16_e8e9(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le16, set_le16)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// unfilter: e8, e9, e8e9
|
|
||||||
static int u_ct16_e8(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe8), 0 - a - f->addvalue, get_le16, set_le16)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int u_ct16_e9(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe9), 0 - a - f->addvalue, get_le16, set_le16)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int u_ct16_e8e9(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_le16, set_le16)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// scan: e8, e9, e8e9
|
|
||||||
static int s_ct16_e8(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe8), a + f->addvalue, get_le16, set_dummy)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int s_ct16_e9(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe9), a + f->addvalue, get_le16, set_dummy)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int s_ct16_e8e9(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le16, set_dummy)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// filter: e8, e9, e8e9 with bswap le->be
|
|
||||||
static int f_ct16_e8_bswap_le(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe8), a + f->addvalue, get_le16, set_be16)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int f_ct16_e9_bswap_le(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe9), a + f->addvalue, get_le16, set_be16)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int f_ct16_e8e9_bswap_le(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le16, set_be16)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// unfilter: e8, e9, e8e9 with bswap le->be
|
|
||||||
static int u_ct16_e8_bswap_le(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe8), 0 - a - f->addvalue, get_be16, set_le16)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int u_ct16_e9_bswap_le(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe9), 0 - a - f->addvalue, get_be16, set_le16)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int u_ct16_e8e9_bswap_le(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_be16, set_le16)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// scan: e8, e9, e8e9 with bswap le->be
|
|
||||||
static int s_ct16_e8_bswap_le(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe8), a + f->addvalue, get_be16, set_dummy)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int s_ct16_e9_bswap_le(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe9), a + f->addvalue, get_be16, set_dummy)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int s_ct16_e8e9_bswap_le(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_be16, set_dummy)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// filter: e8, e9, e8e9 with bswap be->le
|
|
||||||
static int f_ct16_e8_bswap_be(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe8), a + f->addvalue, get_be16, set_le16)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int f_ct16_e9_bswap_be(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe9), a + f->addvalue, get_be16, set_le16)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int f_ct16_e8e9_bswap_be(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_be16, set_le16)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// unfilter: e8, e9, e8e9 with bswap be->le
|
|
||||||
static int u_ct16_e8_bswap_be(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe8), 0 - a - f->addvalue, get_le16, set_be16)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int u_ct16_e9_bswap_be(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe9), 0 - a - f->addvalue, get_le16, set_be16)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int u_ct16_e8e9_bswap_be(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_le16, set_be16)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// scan: e8, e9, e8e9 with bswap be->le
|
|
||||||
static int s_ct16_e8_bswap_be(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe8), a + f->addvalue, get_le16, set_dummy)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int s_ct16_e9_bswap_be(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe9), a + f->addvalue, get_le16, set_dummy)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int s_ct16_e8e9_bswap_be(Filter *f)
|
|
||||||
{
|
|
||||||
CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le16, set_dummy)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#undef CT16
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// 32-bit calltrick ("naive")
|
// simple filters: calltrick / swaptrick / delta / ...
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#define CT32(f, cond, addvalue, get, set) \
|
#include "filter/ct.h"
|
||||||
upx_byte *b = f->buf; \
|
#include "filter/sw.h"
|
||||||
upx_byte *b_end = b + f->buf_len - 5; \
|
#include "filter/ctsw.h"
|
||||||
do { \
|
|
||||||
if (cond) \
|
|
||||||
{ \
|
|
||||||
b += 1; \
|
|
||||||
unsigned a = (unsigned) (b - f->buf); \
|
|
||||||
f->lastcall = a; \
|
|
||||||
set(b, get(b) + (addvalue)); \
|
|
||||||
f->calls++; \
|
|
||||||
b += 4 - 1; \
|
|
||||||
} \
|
|
||||||
} while (++b < b_end); \
|
|
||||||
if (f->lastcall) f->lastcall += 4; \
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
|
#include "filter/sub8.h"
|
||||||
// filter: e8, e9, e8e9
|
#include "filter/sub16.h"
|
||||||
static int f_ct32_e8(Filter *f)
|
#include "filter/sub32.h"
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe8), a + f->addvalue, get_le32, set_le32)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int f_ct32_e9(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe9), a + f->addvalue, get_le32, set_le32)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int f_ct32_e8e9(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le32, set_le32)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// unfilter: e8, e9, e8e9
|
|
||||||
static int u_ct32_e8(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe8), 0 - a - f->addvalue, get_le32, set_le32)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int u_ct32_e9(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe9), 0 - a - f->addvalue, get_le32, set_le32)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int u_ct32_e8e9(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_le32, set_le32)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// scan: e8, e9, e8e9
|
|
||||||
static int s_ct32_e8(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe8), a + f->addvalue, get_le32, set_dummy)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int s_ct32_e9(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe9), a + f->addvalue, get_le32, set_dummy)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int s_ct32_e8e9(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le32, set_dummy)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// filter: e8, e9, e8e9 with bswap le->be
|
|
||||||
static int f_ct32_e8_bswap_le(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe8), a + f->addvalue, get_le32, set_be32)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int f_ct32_e9_bswap_le(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe9), a + f->addvalue, get_le32, set_be32)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int f_ct32_e8e9_bswap_le(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le32, set_be32)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// unfilter: e8, e9, e8e9 with bswap le->be
|
|
||||||
static int u_ct32_e8_bswap_le(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe8), 0 - a - f->addvalue, get_be32, set_le32)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int u_ct32_e9_bswap_le(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe9), 0 - a - f->addvalue, get_be32, set_le32)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int u_ct32_e8e9_bswap_le(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_be32, set_le32)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// scan: e8, e9, e8e9 with bswap le->be
|
|
||||||
static int s_ct32_e8_bswap_le(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe8), a + f->addvalue, get_be32, set_dummy)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int s_ct32_e9_bswap_le(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe9), a + f->addvalue, get_be32, set_dummy)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int s_ct32_e8e9_bswap_le(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_be32, set_dummy)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// filter: e8, e9, e8e9 with bswap be->le
|
|
||||||
static int f_ct32_e8_bswap_be(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe8), a + f->addvalue, get_be32, set_le32)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int f_ct32_e9_bswap_be(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe9), a + f->addvalue, get_be32, set_le32)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int f_ct32_e8e9_bswap_be(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_be32, set_le32)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// unfilter: e8, e9, e8e9 with bswap be->le
|
|
||||||
static int u_ct32_e8_bswap_be(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe8), 0 - a - f->addvalue, get_le32, set_be32)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int u_ct32_e9_bswap_be(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe9), 0 - a - f->addvalue, get_le32, set_be32)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int u_ct32_e8e9_bswap_be(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_le32, set_be32)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// scan: e8, e9, e8e9 with bswap be->le
|
|
||||||
static int s_ct32_e8_bswap_be(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe8), a + f->addvalue, get_le32, set_dummy)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int s_ct32_e9_bswap_be(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe9), a + f->addvalue, get_le32, set_dummy)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int s_ct32_e8e9_bswap_be(Filter *f)
|
|
||||||
{
|
|
||||||
CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le32, set_dummy)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#undef CT32
|
|
||||||
|
|
||||||
#undef set_dummy
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// 32-bit calltrick with cto ("clever")
|
// cto calltrick
|
||||||
//
|
|
||||||
// This version is more sophisticated because it only
|
|
||||||
// tries to change actual calls and/or jumps.
|
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include "fcto_ml.ch"
|
#define COND(b,x) (b[x] == 0xe8)
|
||||||
|
#define F f_cto32_e8_bswap_le
|
||||||
|
#define U u_cto32_e8_bswap_le
|
||||||
|
#include "filter/cto.h"
|
||||||
|
#define F s_cto32_e8_bswap_le
|
||||||
|
#include "filter/cto.h"
|
||||||
|
#undef COND
|
||||||
|
|
||||||
|
#define COND(b,x) (b[x] == 0xe9)
|
||||||
|
#define F f_cto32_e9_bswap_le
|
||||||
|
#define U u_cto32_e9_bswap_le
|
||||||
|
#include "filter/cto.h"
|
||||||
|
#define F s_cto32_e9_bswap_le
|
||||||
|
#include "filter/cto.h"
|
||||||
|
#undef COND
|
||||||
|
|
||||||
|
#define COND(b,x) (b[x] == 0xe8 || b[x] == 0xe9)
|
||||||
|
#define F f_cto32_e8e9_bswap_le
|
||||||
|
#define U u_cto32_e8e9_bswap_le
|
||||||
|
#include "filter/cto.h"
|
||||||
|
#define F s_cto32_e8e9_bswap_le
|
||||||
|
#include "filter/cto.h"
|
||||||
|
#undef COND
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// cto calltrick with jmp
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#define COND(b,x,lastcall) (b[x] == 0xe8 || b[x] == 0xe9)
|
||||||
|
#define F f_ctoj32_e8e9_bswap_le
|
||||||
|
#define U u_ctoj32_e8e9_bswap_le
|
||||||
|
#include "filter/ctoj.h"
|
||||||
|
#define F s_ctoj32_e8e9_bswap_le
|
||||||
|
#include "filter/ctoj.h"
|
||||||
|
#undef COND
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// cto calltrick with jmp, optional jcc
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#define COND1(b,x) (b[x] == 0xe8 || b[x] == 0xe9)
|
||||||
|
#define COND2(b,x,lc) (lc!=(x) && 0xf==b[(x)-1] && 0x80<=b[x] && b[x]<=0x8f)
|
||||||
|
#define COND(b,x,lc,id) (COND1(b,x) || ((9<=(0xf&(id))) && COND2(b,x,lc)))
|
||||||
|
#define F f_ctok32_e8e9_bswap_le
|
||||||
|
#define U u_ctok32_e8e9_bswap_le
|
||||||
|
#include "filter/ctok.h"
|
||||||
|
#define F s_ctok32_e8e9_bswap_le
|
||||||
|
#include "filter/ctok.h"
|
||||||
|
#undef COND
|
||||||
|
#undef COND2
|
||||||
|
#undef COND1
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// cto calltrick with jmp and jcc and relative renumbering
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#define COND_CALL(which,b,x) ((which = 0), b[x] == 0xe8)
|
||||||
|
#define COND_JMP( which,b,x) ((which = 1), b[x] == 0xe9)
|
||||||
|
#define COND_JCC( which,b,lastcall,x,y,z) ((which = 2), \
|
||||||
|
(lastcall!=(x) && 0xf==b[y] && 0x80<=b[z] && b[z]<=0x8f))
|
||||||
|
#define COND1(which,b,x) (COND_CALL(which,b,x) || COND_JMP(which,b,x))
|
||||||
|
#define COND2(which,b,lastcall,x,y,z) COND_JCC(which,b,lastcall,x,y,z)
|
||||||
|
|
||||||
|
#define CONDF(which,b,x,lastcall) \
|
||||||
|
(COND1(which,b,x) || COND2(which,b,lastcall,x,(x)-1, x ))
|
||||||
|
#define CONDU(which,b,x,lastcall) \
|
||||||
|
(COND1(which,b,x) || COND2(which,b,lastcall,x, x ,(x)-1))
|
||||||
|
|
||||||
|
#define F f_ctojr32_e8e9_bswap_le
|
||||||
|
#define U u_ctojr32_e8e9_bswap_le
|
||||||
|
#include "filter/ctojr.h"
|
||||||
|
#define F s_ctojr32_e8e9_bswap_le
|
||||||
|
#include "filter/ctojr.h"
|
||||||
|
|
||||||
|
#undef CONDU
|
||||||
|
#undef CONDF
|
||||||
|
#undef COND2
|
||||||
|
#undef COND1
|
||||||
|
#undef COND_JCC
|
||||||
|
#undef COND_JMP
|
||||||
|
#undef COND_CALL
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
@@ -409,8 +152,9 @@ static int s_ct32_e8e9_bswap_be(Filter *f)
|
|||||||
const FilterImp::FilterEntry FilterImp::filters[] = {
|
const FilterImp::FilterEntry FilterImp::filters[] = {
|
||||||
// no filter
|
// no filter
|
||||||
{ 0x00, 0, 0, NULL, NULL, NULL },
|
{ 0x00, 0, 0, NULL, NULL, NULL },
|
||||||
|
|
||||||
// 16-bit calltrick
|
// 16-bit calltrick
|
||||||
{ 0x01, 4, 0, f_ct16_e8, u_ct16_e8, s_ct16_e8,},
|
{ 0x01, 4, 0, f_ct16_e8, u_ct16_e8, s_ct16_e8 },
|
||||||
{ 0x02, 4, 0, f_ct16_e9, u_ct16_e9, s_ct16_e9 },
|
{ 0x02, 4, 0, f_ct16_e9, u_ct16_e9, s_ct16_e9 },
|
||||||
{ 0x03, 4, 0, f_ct16_e8e9, u_ct16_e8e9, s_ct16_e8e9 },
|
{ 0x03, 4, 0, f_ct16_e8e9, u_ct16_e8e9, s_ct16_e8e9 },
|
||||||
{ 0x04, 4, 0, f_ct16_e8_bswap_le, u_ct16_e8_bswap_le, s_ct16_e8_bswap_le },
|
{ 0x04, 4, 0, f_ct16_e8_bswap_le, u_ct16_e8_bswap_le, s_ct16_e8_bswap_le },
|
||||||
@@ -419,6 +163,16 @@ const FilterImp::FilterEntry FilterImp::filters[] = {
|
|||||||
{ 0x07, 4, 0, f_ct16_e8_bswap_be, u_ct16_e8_bswap_be, s_ct16_e8_bswap_be },
|
{ 0x07, 4, 0, f_ct16_e8_bswap_be, u_ct16_e8_bswap_be, s_ct16_e8_bswap_be },
|
||||||
{ 0x08, 4, 0, f_ct16_e9_bswap_be, u_ct16_e9_bswap_be, s_ct16_e9_bswap_be },
|
{ 0x08, 4, 0, f_ct16_e9_bswap_be, u_ct16_e9_bswap_be, s_ct16_e9_bswap_be },
|
||||||
{ 0x09, 4, 0, f_ct16_e8e9_bswap_be, u_ct16_e8e9_bswap_be, s_ct16_e8e9_bswap_be },
|
{ 0x09, 4, 0, f_ct16_e8e9_bswap_be, u_ct16_e8e9_bswap_be, s_ct16_e8e9_bswap_be },
|
||||||
|
|
||||||
|
// 16-bit swaptrick
|
||||||
|
{ 0x0a, 4, 0, f_sw16_e8, u_sw16_e8, s_sw16_e8 },
|
||||||
|
{ 0x0b, 4, 0, f_sw16_e9, u_sw16_e9, s_sw16_e9 },
|
||||||
|
{ 0x0c, 4, 0, f_sw16_e8e9, u_sw16_e8e9, s_sw16_e8e9 },
|
||||||
|
|
||||||
|
// 16-bit call-/swaptrick
|
||||||
|
{ 0x0d, 4, 0, f_ctsw16_e8_e9, u_ctsw16_e8_e9, s_ctsw16_e8_e9 },
|
||||||
|
{ 0x0e, 4, 0, f_ctsw16_e9_e8, u_ctsw16_e9_e8, s_ctsw16_e9_e8 },
|
||||||
|
|
||||||
// 32-bit calltrick
|
// 32-bit calltrick
|
||||||
{ 0x11, 6, 0, f_ct32_e8, u_ct32_e8, s_ct32_e8 },
|
{ 0x11, 6, 0, f_ct32_e8, u_ct32_e8, s_ct32_e8 },
|
||||||
{ 0x12, 6, 0, f_ct32_e9, u_ct32_e9, s_ct32_e9 },
|
{ 0x12, 6, 0, f_ct32_e9, u_ct32_e9, s_ct32_e9 },
|
||||||
@@ -429,18 +183,53 @@ const FilterImp::FilterEntry FilterImp::filters[] = {
|
|||||||
{ 0x17, 6, 0, f_ct32_e8_bswap_be, u_ct32_e8_bswap_be, s_ct32_e8_bswap_be },
|
{ 0x17, 6, 0, f_ct32_e8_bswap_be, u_ct32_e8_bswap_be, s_ct32_e8_bswap_be },
|
||||||
{ 0x18, 6, 0, f_ct32_e9_bswap_be, u_ct32_e9_bswap_be, s_ct32_e9_bswap_be },
|
{ 0x18, 6, 0, f_ct32_e9_bswap_be, u_ct32_e9_bswap_be, s_ct32_e9_bswap_be },
|
||||||
{ 0x19, 6, 0, f_ct32_e8e9_bswap_be, u_ct32_e8e9_bswap_be, s_ct32_e8e9_bswap_be },
|
{ 0x19, 6, 0, f_ct32_e8e9_bswap_be, u_ct32_e8e9_bswap_be, s_ct32_e8e9_bswap_be },
|
||||||
|
|
||||||
|
// 32-bit swaptrick
|
||||||
|
{ 0x1a, 6, 0, f_sw32_e8, u_sw32_e8, s_sw32_e8 },
|
||||||
|
{ 0x1b, 6, 0, f_sw32_e9, u_sw32_e9, s_sw32_e9 },
|
||||||
|
{ 0x1c, 6, 0, f_sw32_e8e9, u_sw32_e8e9, s_sw32_e8e9 },
|
||||||
|
|
||||||
|
// 32-bit call-/swaptrick
|
||||||
|
{ 0x1d, 6, 0, f_ctsw32_e8_e9, u_ctsw32_e8_e9, s_ctsw32_e8_e9 },
|
||||||
|
{ 0x1e, 6, 0, f_ctsw32_e9_e8, u_ctsw32_e9_e8, s_ctsw32_e9_e8 },
|
||||||
|
|
||||||
// 32-bit cto calltrick
|
// 32-bit cto calltrick
|
||||||
{ 0x21, 6, 0x00ffffff, f_cto32_e8, u_cto32_e8, s_cto32_e8 },
|
|
||||||
{ 0x22, 6, 0x00ffffff, f_cto32_e9, u_cto32_e9, s_cto32_e9 },
|
|
||||||
{ 0x23, 6, 0x00ffffff, f_cto32_e8e9, u_cto32_e8e9, s_cto32_e8e9 },
|
|
||||||
{ 0x24, 6, 0x00ffffff, f_cto32_e8_bswap_le, u_cto32_e8_bswap_le, s_cto32_e8_bswap_le },
|
{ 0x24, 6, 0x00ffffff, f_cto32_e8_bswap_le, u_cto32_e8_bswap_le, s_cto32_e8_bswap_le },
|
||||||
{ 0x25, 6, 0x00ffffff, f_cto32_e9_bswap_le, u_cto32_e9_bswap_le, s_cto32_e9_bswap_le },
|
{ 0x25, 6, 0x00ffffff, f_cto32_e9_bswap_le, u_cto32_e9_bswap_le, s_cto32_e9_bswap_le },
|
||||||
{ 0x26, 6, 0x00ffffff, f_cto32_e8e9_bswap_le, u_cto32_e8e9_bswap_le, s_cto32_e8e9_bswap_le },
|
{ 0x26, 6, 0x00ffffff, f_cto32_e8e9_bswap_le, u_cto32_e8e9_bswap_le, s_cto32_e8e9_bswap_le },
|
||||||
{ 0x27, 6, 0x00ffffff, f_cto32_e8_bswap_be, u_cto32_e8_bswap_be, s_cto32_e8_bswap_be },
|
|
||||||
{ 0x28, 6, 0x00ffffff, f_cto32_e9_bswap_be, u_cto32_e9_bswap_be, s_cto32_e9_bswap_be },
|
// 32-bit cto calltrick with jmp
|
||||||
{ 0x29, 6, 0x00ffffff, f_cto32_e8e9_bswap_be, u_cto32_e8e9_bswap_be, s_cto32_e8e9_bswap_be },
|
{ 0x36, 6, 0x00ffffff, f_ctoj32_e8e9_bswap_le, u_ctoj32_e8e9_bswap_le, s_ctoj32_e8e9_bswap_le },
|
||||||
// 32-bit cto calltrick + jmp
|
|
||||||
{ 0x36, 6, 0x00ffffff, f_ctjo32_e8e9_bswap_le, u_ctjo32_e8e9_bswap_le, s_ctjo32_e8e9_bswap_le },
|
// 32-bit calltrick with jmp, optional jcc; runtime can unfilter more than one block
|
||||||
|
{ 0x46, 6, 0x00ffffff, f_ctok32_e8e9_bswap_le, u_ctok32_e8e9_bswap_le, s_ctok32_e8e9_bswap_le },
|
||||||
|
{ 0x49, 6, 0x00ffffff, f_ctok32_e8e9_bswap_le, u_ctok32_e8e9_bswap_le, s_ctok32_e8e9_bswap_le },
|
||||||
|
|
||||||
|
// 32-bit cto calltrick with jmp and jcc(swap 0x0f/0x8Y) and relative renumbering
|
||||||
|
{ 0x80, 8, 0x00ffffff, f_ctojr32_e8e9_bswap_le, u_ctojr32_e8e9_bswap_le, s_ctojr32_e8e9_bswap_le },
|
||||||
|
{ 0x81, 8, 0x00ffffff, f_ctojr32_e8e9_bswap_le, u_ctojr32_e8e9_bswap_le, s_ctojr32_e8e9_bswap_le },
|
||||||
|
{ 0x82, 8, 0x00ffffff, f_ctojr32_e8e9_bswap_le, u_ctojr32_e8e9_bswap_le, s_ctojr32_e8e9_bswap_le },
|
||||||
|
{ 0x83, 8, 0x00ffffff, f_ctojr32_e8e9_bswap_le, u_ctojr32_e8e9_bswap_le, s_ctojr32_e8e9_bswap_le },
|
||||||
|
{ 0x84, 8, 0x00ffffff, f_ctojr32_e8e9_bswap_le, u_ctojr32_e8e9_bswap_le, s_ctojr32_e8e9_bswap_le },
|
||||||
|
{ 0x85, 8, 0x00ffffff, f_ctojr32_e8e9_bswap_le, u_ctojr32_e8e9_bswap_le, s_ctojr32_e8e9_bswap_le },
|
||||||
|
{ 0x86, 8, 0x00ffffff, f_ctojr32_e8e9_bswap_le, u_ctojr32_e8e9_bswap_le, s_ctojr32_e8e9_bswap_le },
|
||||||
|
{ 0x87, 8, 0x00ffffff, f_ctojr32_e8e9_bswap_le, u_ctojr32_e8e9_bswap_le, s_ctojr32_e8e9_bswap_le },
|
||||||
|
|
||||||
|
// simple delta filter
|
||||||
|
{ 0x90, 2, 0, f_sub8_1, u_sub8_1, s_sub8_1 },
|
||||||
|
{ 0x91, 3, 0, f_sub8_2, u_sub8_2, s_sub8_2 },
|
||||||
|
{ 0x92, 4, 0, f_sub8_3, u_sub8_3, s_sub8_3 },
|
||||||
|
{ 0x93, 5, 0, f_sub8_4, u_sub8_4, s_sub8_4 },
|
||||||
|
|
||||||
|
{ 0xa0,99, 0, f_sub16_1, u_sub16_1, s_sub16_1 },
|
||||||
|
{ 0xa1,99, 0, f_sub16_2, u_sub16_2, s_sub16_2 },
|
||||||
|
{ 0xa2,99, 0, f_sub16_3, u_sub16_3, s_sub16_3 },
|
||||||
|
{ 0xa3,99, 0, f_sub16_4, u_sub16_4, s_sub16_4 },
|
||||||
|
|
||||||
|
{ 0xb0,99, 0, f_sub32_1, u_sub32_1, s_sub32_1 },
|
||||||
|
{ 0xb1,99, 0, f_sub32_2, u_sub32_2, s_sub32_2 },
|
||||||
|
{ 0xb2,99, 0, f_sub32_3, u_sub32_3, s_sub32_3 },
|
||||||
|
{ 0xb3,99, 0, f_sub32_4, u_sub32_4, s_sub32_4 },
|
||||||
};
|
};
|
||||||
|
|
||||||
const int FilterImp::n_filters = HIGH(filters);
|
const int FilterImp::n_filters = HIGH(filters);
|
||||||
|
|||||||
+93
-28
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -44,13 +44,24 @@ void show_head(void)
|
|||||||
return;
|
return;
|
||||||
head_done = 1;
|
head_done = 1;
|
||||||
|
|
||||||
|
#define V(x) (strcmp(UPX_VERSION_STRING, UPX_VERSION_STRING4) ? UPX_VERSION_STRING : UPX_VERSION_STRING x)
|
||||||
fg = con_fg(f,FG_GREEN);
|
fg = con_fg(f,FG_GREEN);
|
||||||
con_fprintf(f,
|
con_fprintf(f,
|
||||||
" Ultimate Packer for eXecutables\n"
|
" Ultimate Packer for eXecutables\n"
|
||||||
" Copyright (C) 1996, 1997, 1998, 1999, 2000\n"
|
" Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002\n"
|
||||||
"UPX v%-12sMarkus F.X.J. Oberhumer & Laszlo Molnar%21s\n\n",
|
"UPX %-12s Markus F.X.J. Oberhumer & Laszlo Molnar %20s\n\n",
|
||||||
UPX_VERSION_STRING, UPX_VERSION_DATE);
|
#if defined(__MFX_DOS)
|
||||||
|
V("d"),
|
||||||
|
#elif defined(__MFX_WIN32)
|
||||||
|
V("w"),
|
||||||
|
#elif 0 && defined(__linux__)
|
||||||
|
V("l"),
|
||||||
|
#else
|
||||||
|
UPX_VERSION_STRING,
|
||||||
|
#endif
|
||||||
|
UPX_VERSION_DATE);
|
||||||
fg = con_fg(f,fg);
|
fg = con_fg(f,fg);
|
||||||
|
#undef V
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -62,7 +73,7 @@ void show_usage(void)
|
|||||||
{
|
{
|
||||||
FILE *f = con_term;
|
FILE *f = con_term;
|
||||||
|
|
||||||
con_fprintf(f,"Usage: %s [-123456788dlthVL] [-qvfk] [-o file] %sfile..\n", progname,
|
con_fprintf(f,"Usage: %s [-123456789dlthVL] [-qvfk] [-o file] %sfile..\n", progname,
|
||||||
#if defined(__DJGPP__) || defined(__EMX__)
|
#if defined(__DJGPP__) || defined(__EMX__)
|
||||||
"[@]");
|
"[@]");
|
||||||
#else
|
#else
|
||||||
@@ -101,7 +112,6 @@ void show_help(int x)
|
|||||||
|
|
||||||
con_fprintf(f,
|
con_fprintf(f,
|
||||||
" -q be quiet -v be verbose\n"
|
" -q be quiet -v be verbose\n"
|
||||||
//" -oFILE write output to `FILE' -c write output to stdout\n"
|
|
||||||
" -oFILE write output to `FILE'\n"
|
" -oFILE write output to `FILE'\n"
|
||||||
//" -f force overwrite of output files and compression of suspicious files\n"
|
//" -f force overwrite of output files and compression of suspicious files\n"
|
||||||
" -f force compression of suspicious files\n"
|
" -f force compression of suspicious files\n"
|
||||||
@@ -131,17 +141,29 @@ void show_help(int x)
|
|||||||
" --overlay=strip strip any extra data attached to the file [dangerous]\n"
|
" --overlay=strip strip any extra data attached to the file [dangerous]\n"
|
||||||
" --overlay=skip don't compress a file with an overlay\n"
|
" --overlay=skip don't compress a file with an overlay\n"
|
||||||
"\n");
|
"\n");
|
||||||
|
#if 1
|
||||||
|
fg = con_fg(f,FG_YELLOW);
|
||||||
|
con_fprintf(f,"Options for atari/tos:\n");
|
||||||
|
fg = con_fg(f,fg);
|
||||||
|
con_fprintf(f,
|
||||||
|
" --all-methods try all available compression methods\n"
|
||||||
|
"\n");
|
||||||
|
#endif
|
||||||
fg = con_fg(f,FG_YELLOW);
|
fg = con_fg(f,FG_YELLOW);
|
||||||
con_fprintf(f,"Options for djgpp2/coff:\n");
|
con_fprintf(f,"Options for djgpp2/coff:\n");
|
||||||
fg = con_fg(f,fg);
|
fg = con_fg(f,fg);
|
||||||
con_fprintf(f,
|
con_fprintf(f,
|
||||||
" --coff produce COFF output [default: EXE]\n"
|
" --coff produce COFF output [default: EXE]\n"
|
||||||
|
" --all-methods try all available compression methods\n"
|
||||||
|
" --all-filters try all available preprocessing filters\n"
|
||||||
"\n");
|
"\n");
|
||||||
fg = con_fg(f,FG_YELLOW);
|
fg = con_fg(f,FG_YELLOW);
|
||||||
con_fprintf(f,"Options for dos/com:\n");
|
con_fprintf(f,"Options for dos/com:\n");
|
||||||
fg = con_fg(f,fg);
|
fg = con_fg(f,fg);
|
||||||
con_fprintf(f,
|
con_fprintf(f,
|
||||||
" --8086 make compressed com work on any 8086\n"
|
" --8086 make compressed com work on any 8086\n"
|
||||||
|
" --all-methods try all available compression methods\n"
|
||||||
|
" --all-filters try all available preprocessing filters\n"
|
||||||
"\n");
|
"\n");
|
||||||
fg = con_fg(f,FG_YELLOW);
|
fg = con_fg(f,FG_YELLOW);
|
||||||
con_fprintf(f,"Options for dos/exe:\n");
|
con_fprintf(f,"Options for dos/exe:\n");
|
||||||
@@ -149,13 +171,52 @@ void show_help(int x)
|
|||||||
con_fprintf(f,
|
con_fprintf(f,
|
||||||
" --8086 make compressed exe work on any 8086\n"
|
" --8086 make compressed exe work on any 8086\n"
|
||||||
" --no-reloc put no relocations in to the exe header\n"
|
" --no-reloc put no relocations in to the exe header\n"
|
||||||
|
" --all-methods try all available compression methods\n"
|
||||||
"\n");
|
"\n");
|
||||||
fg = con_fg(f,FG_YELLOW);
|
fg = con_fg(f,FG_YELLOW);
|
||||||
con_fprintf(f,"Options for dos/sys:\n");
|
con_fprintf(f,"Options for dos/sys:\n");
|
||||||
fg = con_fg(f,fg);
|
fg = con_fg(f,fg);
|
||||||
con_fprintf(f,
|
con_fprintf(f,
|
||||||
" --8086 make compressed sys work on any 8086\n"
|
" --8086 make compressed sys work on any 8086\n"
|
||||||
|
" --all-methods try all available compression methods\n"
|
||||||
|
" --all-filters try all available preprocessing filters\n"
|
||||||
"\n");
|
"\n");
|
||||||
|
#if 0
|
||||||
|
fg = con_fg(f,FG_YELLOW);
|
||||||
|
con_fprintf(f,"Options for linux/386\n");
|
||||||
|
fg = con_fg(f,fg);
|
||||||
|
con_fprintf(f,
|
||||||
|
" --script use /usr/local/lib/upx/upx[bd] as decompressor\n"
|
||||||
|
" --script=/path/upxX use path/upxX as decompressor\n"
|
||||||
|
"\n");
|
||||||
|
#endif
|
||||||
|
#if 1
|
||||||
|
fg = con_fg(f,FG_YELLOW);
|
||||||
|
con_fprintf(f,"Options for ps1/exe:\n");
|
||||||
|
fg = con_fg(f,fg);
|
||||||
|
con_fprintf(f,
|
||||||
|
" --all-methods try all available compression methods\n"
|
||||||
|
" --no-align don't align to mode2 sector format\n"
|
||||||
|
"\n");
|
||||||
|
#endif
|
||||||
|
#if 1
|
||||||
|
fg = con_fg(f,FG_YELLOW);
|
||||||
|
con_fprintf(f,"Options for tmt/adam:\n");
|
||||||
|
fg = con_fg(f,fg);
|
||||||
|
con_fprintf(f,
|
||||||
|
" --all-methods try all available compression methods\n"
|
||||||
|
" --all-filters try all available preprocessing filters\n"
|
||||||
|
"\n");
|
||||||
|
#endif
|
||||||
|
#if 1
|
||||||
|
fg = con_fg(f,FG_YELLOW);
|
||||||
|
con_fprintf(f,"Options for [b]vmlinuz/386\n");
|
||||||
|
fg = con_fg(f,fg);
|
||||||
|
con_fprintf(f,
|
||||||
|
" --all-methods try all available compression methods\n"
|
||||||
|
" --all-filters try all available preprocessing filters\n"
|
||||||
|
"\n");
|
||||||
|
#endif
|
||||||
fg = con_fg(f,FG_YELLOW);
|
fg = con_fg(f,FG_YELLOW);
|
||||||
con_fprintf(f,"Options for watcom/le:\n");
|
con_fprintf(f,"Options for watcom/le:\n");
|
||||||
fg = con_fg(f,fg);
|
fg = con_fg(f,fg);
|
||||||
@@ -174,37 +235,36 @@ void show_help(int x)
|
|||||||
" --compress-resources=0 do not compress any resources at all\n"
|
" --compress-resources=0 do not compress any resources at all\n"
|
||||||
" --strip-relocs=0 do not strip relocations\n"
|
" --strip-relocs=0 do not strip relocations\n"
|
||||||
" --strip-relocs=1 strip relocations [default]\n"
|
" --strip-relocs=1 strip relocations [default]\n"
|
||||||
|
" --all-methods try all available compression methods\n"
|
||||||
|
" --all-filters try all available preprocessing filters\n"
|
||||||
"\n");
|
"\n");
|
||||||
#if 0
|
|
||||||
fg = con_fg(f,FG_YELLOW);
|
|
||||||
con_fprintf(f,"Options for linux/386\n");
|
|
||||||
fg = con_fg(f,fg);
|
|
||||||
con_fprintf(f,
|
|
||||||
" --script use /usr/local/lib/upx/upx[bd] as decompressor\n"
|
|
||||||
" --script=/path/upxX use path/upxX as decompressor\n"
|
|
||||||
"\n");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
con_fprintf(f,
|
con_fprintf(f,
|
||||||
"file.. executables to (de)compress\n"
|
"file.. executables to (de)compress\n"
|
||||||
"\n"
|
"\n");
|
||||||
"This version supports:\n "
|
fg = con_fg(f,FG_YELLOW);
|
||||||
|
con_fprintf(f,"This version supports:\n");
|
||||||
|
fg = con_fg(f,fg);
|
||||||
|
con_fprintf(f," "
|
||||||
"atari/tos, "
|
"atari/tos, "
|
||||||
"bvmlinuz/386, "
|
"bvmlinuz/386, "
|
||||||
"djgpp2/coff, "
|
"djgpp2/coff, "
|
||||||
"dos/com, "
|
"dos/com, "
|
||||||
"dos/exe, "
|
"dos/exe, "
|
||||||
"dos/sys,\n "
|
"dos/sys,\n "
|
||||||
|
//"elks/8086, "
|
||||||
"linux/386, "
|
"linux/386, "
|
||||||
"linux/elf386, "
|
"linux/elf386, "
|
||||||
"linux/sh386, "
|
"linux/sh386, "
|
||||||
|
"ps1/exe, "
|
||||||
"rtm32/pe, "
|
"rtm32/pe, "
|
||||||
"tmt/adam, "
|
"tmt/adam,\n "
|
||||||
"vmlinuz/386,\n "
|
"vmlinuz/386, "
|
||||||
"watcom/le, "
|
"watcom/le, "
|
||||||
|
//"win16/ne, "
|
||||||
"win32/pe"
|
"win32/pe"
|
||||||
"\n\nUPX comes with ABSOLUTELY NO WARRANTY; for details visit http://upx.tsx.org\n"
|
"\n\nUPX comes with ABSOLUTELY NO WARRANTY; for details visit http://upx.sf.net\n"
|
||||||
//"\n\nUPX comes with ABSOLUTELY NO WARRANTY; for details type `upx -L'.\n"
|
//"\n\nUPX comes with ABSOLUTELY NO WARRANTY; for details type `upx -L'.\n"
|
||||||
"");
|
"");
|
||||||
|
|
||||||
@@ -250,14 +310,14 @@ con_fprintf(f,
|
|||||||
);
|
);
|
||||||
int fg = con_fg(f,FG_CYAN);
|
int fg = con_fg(f,FG_CYAN);
|
||||||
con_fprintf(f,
|
con_fprintf(f,
|
||||||
" http://upx.tsx.org\n"
|
" http://upx.sourceforge.net\n"
|
||||||
" http://wildsau.idv.uni-linz.ac.at/mfx/upx.html\n"
|
" http://www.oberhumer.com/opensource/upx/\n"
|
||||||
);
|
);
|
||||||
(void)con_fg(f,FG_ORANGE);
|
(void)con_fg(f,FG_ORANGE);
|
||||||
con_fprintf(f,
|
con_fprintf(f,
|
||||||
"\n"
|
"\n"
|
||||||
" Markus F.X.J. Oberhumer Laszlo Molnar\n"
|
" Markus F.X.J. Oberhumer Laszlo Molnar\n"
|
||||||
" markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu\n"
|
" <mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>\n"
|
||||||
);
|
);
|
||||||
fg = con_fg(f,fg);
|
fg = con_fg(f,fg);
|
||||||
}
|
}
|
||||||
@@ -272,16 +332,21 @@ void show_version(int x)
|
|||||||
FILE *f = stdout;
|
FILE *f = stdout;
|
||||||
UNUSED(x);
|
UNUSED(x);
|
||||||
|
|
||||||
|
#if 0 && defined(__GNUC__)
|
||||||
|
fprintf(f,"upx %s (gcc 0x%lx)\n", UPX_VERSION_STRING, __GNUC_VERSION_HEX__);
|
||||||
|
#else
|
||||||
fprintf(f,"upx %s\n", UPX_VERSION_STRING);
|
fprintf(f,"upx %s\n", UPX_VERSION_STRING);
|
||||||
|
#endif
|
||||||
#if defined(WITH_NRV)
|
#if defined(WITH_NRV)
|
||||||
fprintf(f,"NRV data compression library %s\n", nrv_version_string());
|
fprintf(f,"NRV data compression library %s\n", nrv_version_string());
|
||||||
#endif
|
#endif
|
||||||
#if defined(WITH_UCL)
|
#if defined(WITH_UCL)
|
||||||
fprintf(f,"UCL data compression library %s\n", ucl_version_string());
|
fprintf(f,"UCL data compression library %s\n", ucl_version_string());
|
||||||
#endif
|
#endif
|
||||||
fprintf(f,"Copyright (C) 1996,1997,1998,1999,2000 Markus Franz Xaver Johannes Oberhumer\n");
|
fprintf(f,"Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer\n");
|
||||||
fprintf(f,"Copyright (C) 1996,1997,1998,1999,2000 Laszlo Molnar\n");
|
fprintf(f,"Copyright (C) 1996-2002 Laszlo Molnar\n");
|
||||||
fprintf(f,"Copyright (C) 2000 John F. Reiser\n");
|
fprintf(f,"Copyright (C) 2000-2002 John F. Reiser\n");
|
||||||
|
fprintf(f,"Copyright (C) 2002 Jens Medoch\n");
|
||||||
fprintf(f,"UPX comes with ABSOLUTELY NO WARRANTY; for details type `%s -L'.\n", progname);
|
fprintf(f,"UPX comes with ABSOLUTELY NO WARRANTY; for details type `%s -L'.\n", progname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+28
-11
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -32,8 +32,13 @@
|
|||||||
#include "lefile.h"
|
#include "lefile.h"
|
||||||
|
|
||||||
|
|
||||||
LeFile::LeFile(InputFile *f) : fif(f)
|
LeFile::LeFile(InputFile *f) :
|
||||||
|
fif(f), fof(NULL),
|
||||||
|
le_offset(0), exe_offset(0)
|
||||||
{
|
{
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(le_header_t) == 196);
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(le_object_table_entry_t) == 24);
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(le_pagemap_entry_t) == 4);
|
||||||
memset(&ih,0,sizeof ih);
|
memset(&ih,0,sizeof ih);
|
||||||
memset(&oh,0,sizeof oh);
|
memset(&oh,0,sizeof oh);
|
||||||
iobject_table = oobject_table = NULL;
|
iobject_table = oobject_table = NULL;
|
||||||
@@ -43,7 +48,6 @@ LeFile::LeFile(InputFile *f) : fif(f)
|
|||||||
ifixups = ofixups = NULL;
|
ifixups = ofixups = NULL;
|
||||||
inonres_names = ononres_names = NULL;
|
inonres_names = ononres_names = NULL;
|
||||||
ientries = oentries = NULL;
|
ientries = oentries = NULL;
|
||||||
le_offset = exe_offset = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -168,6 +172,18 @@ void LeFile::writeFixups()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned LeFile::getImageSize() const
|
||||||
|
{
|
||||||
|
unsigned n = 0;
|
||||||
|
if (ih.memory_pages > 0)
|
||||||
|
{
|
||||||
|
n = (ih.memory_pages - 1) * ih.memory_page_size;
|
||||||
|
n += ih.bytes_on_last_page;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void LeFile::readImage()
|
void LeFile::readImage()
|
||||||
{
|
{
|
||||||
soimage = pages*mps;
|
soimage = pages*mps;
|
||||||
@@ -295,7 +311,8 @@ void LeFile::writeFile(OutputFile *f, bool le)
|
|||||||
|
|
||||||
void LeFile::countFixups(unsigned *counts) const
|
void LeFile::countFixups(unsigned *counts) const
|
||||||
{
|
{
|
||||||
memset(counts,0,sizeof(unsigned)*(objects+2));
|
const unsigned o = objects;
|
||||||
|
memset(counts,0,sizeof(unsigned)*(o+2));
|
||||||
// counts[0..objects-1] - # of 32-bit offset relocations in for that objects
|
// counts[0..objects-1] - # of 32-bit offset relocations in for that objects
|
||||||
// counts[objects] - # of selector fixups
|
// counts[objects] - # of selector fixups
|
||||||
// counts[objects+1] - # of self-relative fixups
|
// counts[objects+1] - # of self-relative fixups
|
||||||
@@ -311,7 +328,7 @@ void LeFile::countFixups(unsigned *counts) const
|
|||||||
switch (*fix)
|
switch (*fix)
|
||||||
{
|
{
|
||||||
case 2: // selector fixup
|
case 2: // selector fixup
|
||||||
counts[objects] += 9;
|
counts[o] += 9;
|
||||||
fix += 5;
|
fix += 5;
|
||||||
break;
|
break;
|
||||||
case 0x12: // alias selector
|
case 0x12: // alias selector
|
||||||
@@ -320,7 +337,7 @@ void LeFile::countFixups(unsigned *counts) const
|
|||||||
fix += (fix[1] & 0x10) ? 9 : 7;
|
fix += (fix[1] & 0x10) ? 9 : 7;
|
||||||
break;
|
break;
|
||||||
case 6: // 16:32 pointer
|
case 6: // 16:32 pointer
|
||||||
counts[objects] += 9;
|
counts[o] += 9;
|
||||||
case 7: // 32-bit offset
|
case 7: // 32-bit offset
|
||||||
counts[fix[4]-1] += 4;
|
counts[fix[4]-1] += 4;
|
||||||
fix += (fix[1] & 0x10) ? 9 : 7;
|
fix += (fix[1] & 0x10) ? 9 : 7;
|
||||||
@@ -332,15 +349,15 @@ void LeFile::countFixups(unsigned *counts) const
|
|||||||
fix += ll*2;
|
fix += ll*2;
|
||||||
break;
|
break;
|
||||||
case 8: // 32-bit self relative fixup
|
case 8: // 32-bit self relative fixup
|
||||||
counts[objects+1] += 4;
|
counts[o+1] += 4;
|
||||||
fix += (fix[1] & 0x10) ? 9 : 7;
|
fix += (fix[1] & 0x10) ? 9 : 7;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throwCantPack("unsupported fixup record");
|
throwCantPack("unsupported fixup record");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
counts[objects]++; // extra space for 'ret'
|
counts[o]++; // extra space for 'ret'
|
||||||
counts[objects+1] += 4; // extra space for 0xFFFFFFFF
|
counts[o+1] += 4; // extra space for 0xFFFFFFFF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+14
-10
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -117,7 +117,8 @@ protected:
|
|||||||
LE16 device_id;
|
LE16 device_id;
|
||||||
LE16 ddk_version;
|
LE16 ddk_version;
|
||||||
#endif
|
#endif
|
||||||
};
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
struct le_object_table_entry_t
|
struct le_object_table_entry_t
|
||||||
{
|
{
|
||||||
@@ -127,15 +128,17 @@ protected:
|
|||||||
LE32 pagemap_index;
|
LE32 pagemap_index;
|
||||||
LE32 npages;
|
LE32 npages;
|
||||||
LE32 reserved;
|
LE32 reserved;
|
||||||
};
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
struct le_pagemap_entry_t
|
struct le_pagemap_entry_t
|
||||||
{
|
{
|
||||||
upx_byte h;
|
unsigned char h;
|
||||||
upx_byte m;
|
unsigned char m;
|
||||||
upx_byte l;
|
unsigned char l;
|
||||||
upx_byte type; // 0x00-legal;0x40-iterated;0x80-invalid;0xC0-zeroed
|
unsigned char type; // 0x00-legal;0x40-iterated;0x80-invalid;0xC0-zeroed
|
||||||
};
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
virtual void readObjectTable();
|
virtual void readObjectTable();
|
||||||
virtual void writeObjectTable();
|
virtual void writeObjectTable();
|
||||||
@@ -178,6 +181,7 @@ protected:
|
|||||||
//virtual void decodeImage(){encodeImage();}
|
//virtual void decodeImage(){encodeImage();}
|
||||||
|
|
||||||
void countFixups(unsigned *) const;
|
void countFixups(unsigned *) const;
|
||||||
|
unsigned getImageSize() const;
|
||||||
|
|
||||||
InputFile *fif;
|
InputFile *fif;
|
||||||
OutputFile *fof;
|
OutputFile *fof;
|
||||||
|
|||||||
+29
-19
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -46,7 +46,6 @@ struct Linker::jump
|
|||||||
int toffs;
|
int toffs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Linker::Linker(const void *pdata, int plen, int pinfo)
|
Linker::Linker(const void *pdata, int plen, int pinfo)
|
||||||
{
|
{
|
||||||
iloader = new char[(ilen = plen) + 4096];
|
iloader = new char[(ilen = plen) + 4096];
|
||||||
@@ -54,18 +53,19 @@ Linker::Linker(const void *pdata, int plen, int pinfo)
|
|||||||
oloader = new char[plen];
|
oloader = new char[plen];
|
||||||
olen = 0;
|
olen = 0;
|
||||||
align_hack = 0;
|
align_hack = 0;
|
||||||
|
align_offset = 0;
|
||||||
info = pinfo;
|
info = pinfo;
|
||||||
njumps = nsections = frozen = 0;
|
njumps = nsections = frozen = 0;
|
||||||
jumps = new jump[200];
|
jumps = new jump[200];
|
||||||
sections = new section[200];
|
sections = new section[200];
|
||||||
|
|
||||||
char *p = iloader + info;
|
char *p = iloader + info;
|
||||||
while (get_le32(p) != (unsigned)(-1))
|
while (get32(p) != (unsigned)(-1))
|
||||||
{
|
{
|
||||||
if (get_le32(p))
|
if (get32(p))
|
||||||
{
|
{
|
||||||
memcpy(sections[nsections].name,p,8);
|
memcpy(sections[nsections].name,p,8);
|
||||||
sections[nsections].istart = get_le32(p+8);
|
sections[nsections].istart = get32(p+8);
|
||||||
sections[nsections++].ostart = -1;
|
sections[nsections++].ostart = -1;
|
||||||
p += 12;
|
p += 12;
|
||||||
assert(nsections < 200);
|
assert(nsections < 200);
|
||||||
@@ -73,13 +73,13 @@ Linker::Linker(const void *pdata, int plen, int pinfo)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
int l;
|
int l;
|
||||||
for (l = get_le32(p+4) - 1; iloader[l] == 0; l--)
|
for (l = get32(p+4) - 1; iloader[l] == 0; l--)
|
||||||
;
|
;
|
||||||
|
|
||||||
jumps[njumps].pos = l+1;
|
jumps[njumps].pos = l+1;
|
||||||
jumps[njumps].len = get_le32(p+4)-jumps[njumps].pos;
|
jumps[njumps].len = get32(p+4)-jumps[njumps].pos;
|
||||||
memcpy(jumps[njumps].tsect,p+8,8);
|
memcpy(jumps[njumps].tsect,p+8,8);
|
||||||
jumps[njumps++].toffs = get_le32(p+16);
|
jumps[njumps++].toffs = get32(p+16);
|
||||||
p += 20;
|
p += 20;
|
||||||
assert(njumps < 200);
|
assert(njumps < 200);
|
||||||
}
|
}
|
||||||
@@ -101,7 +101,17 @@ Linker::~Linker()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Linker::addSection(const char *sect)
|
void Linker::setLoaderAlignOffset(int offset)
|
||||||
|
{
|
||||||
|
align_offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hex(char c)
|
||||||
|
{
|
||||||
|
return (c & 0xf) + (c > '9' ? 9 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Linker::addSection(const char *sect)
|
||||||
{
|
{
|
||||||
int ic;
|
int ic;
|
||||||
while (*sect)
|
while (*sect)
|
||||||
@@ -109,14 +119,13 @@ void Linker::addSection(const char *sect)
|
|||||||
if (*sect == '+') // alignment
|
if (*sect == '+') // alignment
|
||||||
{
|
{
|
||||||
if (sect[1] == '0')
|
if (sect[1] == '0')
|
||||||
align_hack = olen;
|
align_hack = olen + align_offset;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ic = (sect[1] & 0xf) + (sect[1] > '9' ? 9 : 0);
|
unsigned j = hex(sect[1]);
|
||||||
ic = (ic + (sect[2] & 0xf) + (sect[2] > '9' ? 9 : 0)
|
j = (hex(sect[2]) - ((olen + align_offset) - align_hack) ) % j;
|
||||||
- (olen - align_hack) % ic) % ic;
|
memset(oloader+olen, (sect[3] == 'C' ? 0x90 : 0), j);
|
||||||
memset(oloader+olen,sect[3] == 'C' ? 0x90 : 0,ic);
|
olen += j;
|
||||||
olen += ic;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -129,11 +138,12 @@ void Linker::addSection(const char *sect)
|
|||||||
olen += sections[ic].len;
|
olen += sections[ic].len;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//printf("%8.8s",section);
|
//printf("%8.8s",sect);
|
||||||
assert(ic!=nsections);
|
assert(ic!=nsections);
|
||||||
}
|
}
|
||||||
sect += 8;
|
sect += 8;
|
||||||
}
|
}
|
||||||
|
return olen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -177,7 +187,7 @@ const char *Linker::getLoader(int *llen)
|
|||||||
if (jumps[ic].len == 1)
|
if (jumps[ic].len == 1)
|
||||||
assert(-128 <= offs && offs <= 127);
|
assert(-128 <= offs && offs <= 127);
|
||||||
|
|
||||||
set_le32(&offs,offs);
|
set32(&offs,offs);
|
||||||
memcpy(oloader+sections[jc].ostart+jumps[ic].pos-sections[jc].istart,&offs,jumps[ic].len);
|
memcpy(oloader+sections[jc].ostart+jumps[ic].pos-sections[jc].istart,&offs,jumps[ic].len);
|
||||||
}
|
}
|
||||||
frozen=1;
|
frozen=1;
|
||||||
|
|||||||
+31
-5
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -34,11 +34,18 @@ class Linker
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Linker(const void *pdata, int plen, int pinfo);
|
Linker(const void *pdata, int plen, int pinfo);
|
||||||
~Linker();
|
virtual ~Linker();
|
||||||
void addSection(const char *sect);
|
int addSection(const char *sect);
|
||||||
void addSection(const char *sname, const void *sdata, unsigned len);
|
void addSection(const char *sname, const void *sdata, unsigned len);
|
||||||
const char *getLoader(int *llen);
|
const char *getLoader(int *llen);
|
||||||
int getSection(const char *name, int *slen) const;
|
int getSection(const char *name, int *slen) const;
|
||||||
|
int getLoaderSize() const { return olen; }
|
||||||
|
void setLoaderAlignOffset(int phase);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// little endian
|
||||||
|
virtual unsigned get32(const void *b) const { return get_le32(b); }
|
||||||
|
virtual void set32(void *b, unsigned v) const { set_le32(b, v); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct section;
|
struct section;
|
||||||
@@ -53,6 +60,7 @@ private:
|
|||||||
int nsections;
|
int nsections;
|
||||||
int frozen;
|
int frozen;
|
||||||
int align_hack;
|
int align_hack;
|
||||||
|
int align_offset;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// disable copy and assignment
|
// disable copy and assignment
|
||||||
@@ -61,6 +69,24 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class BeLinker : public Linker
|
||||||
|
{
|
||||||
|
typedef Linker super;
|
||||||
|
public:
|
||||||
|
BeLinker(const void *pdata, int plen, int pinfo) :
|
||||||
|
super(pdata, plen, pinfo) { }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// big endian
|
||||||
|
virtual unsigned get32(const void *b) const { return get_be32(b); }
|
||||||
|
virtual void set32(void *b, unsigned v) const { set_be32(b, v); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// disable copy and assignment
|
||||||
|
BeLinker(BeLinker const &); // {}
|
||||||
|
BeLinker& operator= (BeLinker const &); // { return *this; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* already included */
|
#endif /* already included */
|
||||||
|
|
||||||
|
|||||||
+199
-78
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,13 +22,20 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "mygetopt.h"
|
#include "mygetopt.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
#include "packer.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if 1 && defined(__DJGPP__)
|
||||||
|
#include <crt0.h>
|
||||||
|
int _crt0_startup_flags = _CRT0_FLAG_UNIX_SBRK;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
@@ -43,7 +50,6 @@ void init_options(struct options_t *o)
|
|||||||
o->cmd = CMD_NONE;
|
o->cmd = CMD_NONE;
|
||||||
o->method = -1;
|
o->method = -1;
|
||||||
o->level = -1;
|
o->level = -1;
|
||||||
o->mem_level = -1;
|
|
||||||
o->filter = -1;
|
o->filter = -1;
|
||||||
|
|
||||||
o->backup = -1;
|
o->backup = -1;
|
||||||
@@ -59,7 +65,10 @@ void init_options(struct options_t *o)
|
|||||||
|
|
||||||
o->w32pe.compress_exports = 1;
|
o->w32pe.compress_exports = 1;
|
||||||
o->w32pe.compress_icons = 2;
|
o->w32pe.compress_icons = 2;
|
||||||
o->w32pe.compress_resources = true;
|
o->w32pe.compress_resources = -1;
|
||||||
|
for (unsigned i = 0; i < HIGH(opt->w32pe.compress_rt); i++)
|
||||||
|
opt->w32pe.compress_rt[i] = -1;
|
||||||
|
opt->w32pe.compress_rt[24] = false; // 24 == RT_MANIFEST
|
||||||
o->w32pe.strip_relocs = -1;
|
o->w32pe.strip_relocs = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,6 +183,14 @@ static void e_optarg(const char *n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void e_optval(const char *n)
|
||||||
|
{
|
||||||
|
fflush(con_term);
|
||||||
|
fprintf(stderr,"%s: invalid value for option `%s'\n", argv0, n);
|
||||||
|
e_exit(EXIT_USAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined(OPTIONS_VAR)
|
#if defined(OPTIONS_VAR)
|
||||||
void e_envopt(const char *n)
|
void e_envopt(const char *n)
|
||||||
{
|
{
|
||||||
@@ -228,6 +245,11 @@ void check_options(int i, int argc)
|
|||||||
opt->backup = 1;
|
opt->backup = 1;
|
||||||
|
|
||||||
check_not_both(opt->to_stdout, opt->output_name != NULL, "--stdout", "-o");
|
check_not_both(opt->to_stdout, opt->output_name != NULL, "--stdout", "-o");
|
||||||
|
if (opt->to_stdout && opt->cmd == CMD_COMPRESS)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"%s: cannot use `--stdout' when compressing\n", argv0);
|
||||||
|
e_usage();
|
||||||
|
}
|
||||||
if (opt->to_stdout || opt->output_name)
|
if (opt->to_stdout || opt->output_name)
|
||||||
{
|
{
|
||||||
if (i + 1 != argc)
|
if (i + 1 != argc)
|
||||||
@@ -270,7 +292,12 @@ static void set_cmd(int cmd)
|
|||||||
static bool set_method(int m, int l)
|
static bool set_method(int m, int l)
|
||||||
{
|
{
|
||||||
if (m > 0)
|
if (m > 0)
|
||||||
|
{
|
||||||
|
if (!Packer::isValidCompressionMethod(m))
|
||||||
|
return false;
|
||||||
opt->method = m;
|
opt->method = m;
|
||||||
|
opt->all_methods = false;
|
||||||
|
}
|
||||||
if (l > 0)
|
if (l > 0)
|
||||||
opt->level = l;
|
opt->level = l;
|
||||||
set_cmd(CMD_COMPRESS);
|
set_cmd(CMD_COMPRESS);
|
||||||
@@ -315,7 +342,7 @@ static void set_script_name(const char *n, bool allow_m)
|
|||||||
fprintf(stderr,"%s: missing script name\n",argv0);
|
fprintf(stderr,"%s: missing script name\n",argv0);
|
||||||
e_usage();
|
e_usage();
|
||||||
}
|
}
|
||||||
if (strlen(n) >= opt->unix.SCRIPT_MAX - 3)
|
if (strlen(n) >= (size_t)opt->unix.SCRIPT_MAX - 3)
|
||||||
{
|
{
|
||||||
fprintf(stderr,"%s: script name too long\n",argv0);
|
fprintf(stderr,"%s: script name too long\n",argv0);
|
||||||
e_usage();
|
e_usage();
|
||||||
@@ -403,10 +430,13 @@ static int do_option(int optc, const char *arg)
|
|||||||
|
|
||||||
switch (optc)
|
switch (optc)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
|
// FIXME: to_stdout doesn't work because of console code mess
|
||||||
//case 'c':
|
//case 'c':
|
||||||
case 517:
|
case 517:
|
||||||
opt->to_stdout = true;
|
opt->to_stdout = true;
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
case 'd':
|
case 'd':
|
||||||
set_cmd(CMD_DECOMPRESS);
|
set_cmd(CMD_DECOMPRESS);
|
||||||
break;
|
break;
|
||||||
@@ -416,7 +446,7 @@ static int do_option(int optc, const char *arg)
|
|||||||
case 'f':
|
case 'f':
|
||||||
opt->force++;
|
opt->force++;
|
||||||
break;
|
break;
|
||||||
case 901:
|
case 902:
|
||||||
set_cmd(CMD_FILEINFO);
|
set_cmd(CMD_FILEINFO);
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
@@ -425,9 +455,11 @@ static int do_option(int optc, const char *arg)
|
|||||||
set_cmd(CMD_HELP);
|
set_cmd(CMD_HELP);
|
||||||
break;
|
break;
|
||||||
case 'h'+256:
|
case 'h'+256:
|
||||||
|
#if 0
|
||||||
/* according to GNU standards */
|
/* according to GNU standards */
|
||||||
set_term(stdout);
|
set_term(stdout);
|
||||||
opt->console = CON_FILE;
|
opt->console = CON_FILE;
|
||||||
|
#endif
|
||||||
show_help(1);
|
show_help(1);
|
||||||
e_exit(EXIT_OK);
|
e_exit(EXIT_OK);
|
||||||
break;
|
break;
|
||||||
@@ -472,6 +504,10 @@ static int do_option(int optc, const char *arg)
|
|||||||
if (!set_method(M_NRV2D_LE32, -1))
|
if (!set_method(M_NRV2D_LE32, -1))
|
||||||
e_method(M_NRV2D_LE32, opt->level);
|
e_method(M_NRV2D_LE32, opt->level);
|
||||||
break;
|
break;
|
||||||
|
case 705:
|
||||||
|
if (!set_method(M_NRV2E_LE32, -1))
|
||||||
|
e_method(M_NRV2E_LE32, opt->level);
|
||||||
|
break;
|
||||||
|
|
||||||
// compression level
|
// compression level
|
||||||
case '1':
|
case '1':
|
||||||
@@ -486,16 +522,18 @@ static int do_option(int optc, const char *arg)
|
|||||||
if (!set_method(-1, optc - '0'))
|
if (!set_method(-1, optc - '0'))
|
||||||
e_method(opt->method, optc);
|
e_method(opt->method, optc);
|
||||||
break;
|
break;
|
||||||
case 900:
|
|
||||||
|
case 901: // --brute
|
||||||
|
opt->all_methods = true;
|
||||||
|
opt->method = -1;
|
||||||
|
opt->all_filters = true;
|
||||||
|
opt->filter = -1;
|
||||||
|
/* fallthrough */
|
||||||
|
case 900: // --best
|
||||||
if (!set_method(-1, 10))
|
if (!set_method(-1, 10))
|
||||||
e_method(opt->method, 10);
|
e_method(opt->method, 10);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// compression memory level
|
|
||||||
case 902:
|
|
||||||
getoptvar(&opt->mem_level, 1, 9);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// misc
|
// misc
|
||||||
case 512:
|
case 512:
|
||||||
opt->console = CON_FILE;
|
opt->console = CON_FILE;
|
||||||
@@ -513,17 +551,27 @@ static int do_option(int optc, const char *arg)
|
|||||||
opt->no_env = true;
|
opt->no_env = true;
|
||||||
break;
|
break;
|
||||||
// compression settings
|
// compression settings
|
||||||
case 525:
|
case 520: // --small
|
||||||
opt->small = 1;
|
if (opt->small < 0)
|
||||||
|
opt->small = 0;
|
||||||
|
opt->small++;
|
||||||
break;
|
break;
|
||||||
case 526:
|
case 521: // --filter=
|
||||||
getoptvar(&opt->filter, 0, 255);
|
getoptvar(&opt->filter, 0, 255);
|
||||||
opt->all_filters = false;
|
opt->all_filters = false;
|
||||||
break;
|
break;
|
||||||
case 527:
|
case 522: // --no-filter
|
||||||
|
opt->filter = 0;
|
||||||
|
opt->all_filters = false;
|
||||||
|
break;
|
||||||
|
case 523: // --all-filters
|
||||||
opt->all_filters = true;
|
opt->all_filters = true;
|
||||||
opt->filter = -1;
|
opt->filter = -1;
|
||||||
break;
|
break;
|
||||||
|
case 524: // --all-methods
|
||||||
|
opt->all_methods = true;
|
||||||
|
opt->method = -1;
|
||||||
|
break;
|
||||||
// compression parms
|
// compression parms
|
||||||
case 531:
|
case 531:
|
||||||
getoptvar(&opt->crp.c_flags, 0, 3);
|
getoptvar(&opt->crp.c_flags, 0, 3);
|
||||||
@@ -544,7 +592,8 @@ static int do_option(int optc, const char *arg)
|
|||||||
getoptvar(&opt->crp.max_match, 16u, ~0u);
|
getoptvar(&opt->crp.max_match, 16u, ~0u);
|
||||||
break;
|
break;
|
||||||
case 537:
|
case 537:
|
||||||
getoptvar(&opt->crp.m_size, 1024u, 512*1024u);
|
if (getoptvar(&opt->crp.m_size, 10000u, (unsigned)999999u) != 0)
|
||||||
|
e_optval("--crp-ms=");
|
||||||
break;
|
break;
|
||||||
// backup
|
// backup
|
||||||
case 'k':
|
case 'k':
|
||||||
@@ -636,10 +685,19 @@ static int do_option(int optc, const char *arg)
|
|||||||
getoptvar(&opt->unix.blocksize, 8192u, ~0u);
|
getoptvar(&opt->unix.blocksize, 8192u, ~0u);
|
||||||
break;
|
break;
|
||||||
case 661:
|
case 661:
|
||||||
|
opt->unix.force_execve = true;
|
||||||
|
break;
|
||||||
|
case 662:
|
||||||
opt->unix.script_name = "/usr/local/lib/upx/upxX";
|
opt->unix.script_name = "/usr/local/lib/upx/upxX";
|
||||||
if (mfx_optarg && mfx_optarg[0])
|
if (mfx_optarg && mfx_optarg[0])
|
||||||
set_script_name(mfx_optarg,1);
|
set_script_name(mfx_optarg,1);
|
||||||
break;
|
break;
|
||||||
|
case 663:
|
||||||
|
opt->unix.ptinterp = true;
|
||||||
|
break;
|
||||||
|
case 670:
|
||||||
|
opt->ps1.no_align = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case '\0':
|
case '\0':
|
||||||
return -1;
|
return -1;
|
||||||
@@ -661,10 +719,11 @@ static int get_options(int argc, char **argv)
|
|||||||
static const struct mfx_option longopts[] =
|
static const struct mfx_option longopts[] =
|
||||||
{
|
{
|
||||||
// commands
|
// commands
|
||||||
{"best", 0, 0, 900}, // compress best
|
{"best", 0x10, 0, 900}, // compress best
|
||||||
|
{"brute", 0x10, 0, 901}, // compress best, brute force
|
||||||
{"decompress", 0, 0, 'd'}, // decompress
|
{"decompress", 0, 0, 'd'}, // decompress
|
||||||
{"fast", 0, 0, '1'}, // compress faster
|
{"fast", 0x10, 0, '1'}, // compress faster
|
||||||
{"fileinfo", 0x10, 0, 901}, // display info about file
|
{"fileinfo", 0x10, 0, 902}, // display info about file
|
||||||
{"help", 0, 0, 'h'+256}, // give help
|
{"help", 0, 0, 'h'+256}, // give help
|
||||||
{"license", 0, 0, 'L'}, // display software license
|
{"license", 0, 0, 'L'}, // display software license
|
||||||
{"list", 0, 0, 'l'}, // list compressed exe
|
{"list", 0, 0, 'l'}, // list compressed exe
|
||||||
@@ -682,8 +741,11 @@ static const struct mfx_option longopts[] =
|
|||||||
{"output", 0x21, 0, 'o'},
|
{"output", 0x21, 0, 'o'},
|
||||||
{"quiet", 0, 0, 'q'}, // quiet mode
|
{"quiet", 0, 0, 'q'}, // quiet mode
|
||||||
{"silent", 0, 0, 'q'}, // quiet mode
|
{"silent", 0, 0, 'q'}, // quiet mode
|
||||||
|
#if 0
|
||||||
|
// FIXME: to_stdout doesn't work because of console code mess
|
||||||
{"stdout", 0x10, 0, 517}, // write output on standard output
|
{"stdout", 0x10, 0, 517}, // write output on standard output
|
||||||
{"to-stdout", 0x10, 0, 517}, // write output on standard output
|
{"to-stdout", 0x10, 0, 517}, // write output on standard output
|
||||||
|
#endif
|
||||||
{"verbose", 0, 0, 'v'}, // verbose mode
|
{"verbose", 0, 0, 'v'}, // verbose mode
|
||||||
|
|
||||||
// backup options
|
// backup options
|
||||||
@@ -710,17 +772,15 @@ static const struct mfx_option longopts[] =
|
|||||||
{"color", 0, 0, 514},
|
{"color", 0, 0, 514},
|
||||||
|
|
||||||
// compression method
|
// compression method
|
||||||
{"2b", 0x10, 0, 702}, // --2b
|
|
||||||
{"n2b", 0x10, 0, 702}, // --n2b
|
|
||||||
{"nrv2b", 0x10, 0, 702}, // --nrv2b
|
{"nrv2b", 0x10, 0, 702}, // --nrv2b
|
||||||
{"2d", 0x10, 0, 704}, // --2d
|
|
||||||
{"n2d", 0x10, 0, 704}, // --n2d
|
|
||||||
{"nrv2d", 0x10, 0, 704}, // --nrv2d
|
{"nrv2d", 0x10, 0, 704}, // --nrv2d
|
||||||
|
{"nrv2e", 0x10, 0, 705}, // --nrv2e
|
||||||
// compression settings
|
// compression settings
|
||||||
{"all-filters", 0x10, 0, 527},
|
{"all-filters", 0x10, 0, 523},
|
||||||
{"filter", 0x31, 0, 526}, // --filter=
|
{"all-methods", 0x10, 0, 524},
|
||||||
{"mem", 0x31, 0, 902}, // --mem=
|
{"filter", 0x31, 0, 521}, // --filter=
|
||||||
{"small", 0x10, 0, 525},
|
{"no-filter", 0x10, 0, 522},
|
||||||
|
{"small", 0x10, 0, 520},
|
||||||
// compression runtime parameters
|
// compression runtime parameters
|
||||||
{"crp-cf", 0x31, 0, 531},
|
{"crp-cf", 0x31, 0, 531},
|
||||||
{"crp-sl", 0x31, 0, 532},
|
{"crp-sl", 0x31, 0, 532},
|
||||||
@@ -741,9 +801,11 @@ static const struct mfx_option longopts[] =
|
|||||||
// dos/sys
|
// dos/sys
|
||||||
// unix
|
// unix
|
||||||
{"blocksize", 0x31, 0, 660}, // --blocksize=
|
{"blocksize", 0x31, 0, 660}, // --blocksize=
|
||||||
|
{"force-execve", 0x10, 0, 661}, // force linux/386 execve format
|
||||||
#if 0
|
#if 0
|
||||||
{"script", 0x31, 0, 661}, // --script=
|
{"script", 0x31, 0, 662}, // --script=
|
||||||
#endif
|
#endif
|
||||||
|
{"ptinterp", 0, 0, 663}, // linux/elf386 PT_INTERP program
|
||||||
// watcom/le
|
// watcom/le
|
||||||
{"le", 0, 0, 620}, // produce LE output
|
{"le", 0, 0, 620}, // produce LE output
|
||||||
// win32/pe
|
// win32/pe
|
||||||
@@ -751,8 +813,10 @@ static const struct mfx_option longopts[] =
|
|||||||
{"compress-icons", 2, 0, 631},
|
{"compress-icons", 2, 0, 631},
|
||||||
{"compress-resources", 2, 0, 632},
|
{"compress-resources", 2, 0, 632},
|
||||||
{"strip-relocs", 2, 0, 633},
|
{"strip-relocs", 2, 0, 633},
|
||||||
|
// ps1/exe
|
||||||
|
{"no-align", 0x10, 0, 670},
|
||||||
|
|
||||||
{ 0, 0, 0, 0 }
|
{ NULL, 0, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
int optc, longind;
|
int optc, longind;
|
||||||
@@ -780,8 +844,9 @@ static void get_envoptions(int argc, char **argv)
|
|||||||
static const struct mfx_option longopts[] =
|
static const struct mfx_option longopts[] =
|
||||||
{
|
{
|
||||||
// commands
|
// commands
|
||||||
{"best", 0, 0, 900}, // compress best
|
{"best", 0x10, 0, 900}, // compress best
|
||||||
{"fast", 0, 0, '1'}, // compress faster
|
{"brute", 0x10, 0, 901}, // compress best, brute force
|
||||||
|
{"fast", 0x10, 0, '1'}, // compress faster
|
||||||
|
|
||||||
// options
|
// options
|
||||||
{"info", 0, 0, 'i'}, // info mode
|
{"info", 0, 0, 'i'}, // info mode
|
||||||
@@ -819,7 +884,7 @@ static const struct mfx_option longopts[] =
|
|||||||
{"compress-resources", 2, 0, 632},
|
{"compress-resources", 2, 0, 632},
|
||||||
{"strip-relocs", 2, 0, 633},
|
{"strip-relocs", 2, 0, 633},
|
||||||
|
|
||||||
{ 0, 0, 0, 0 }
|
{ NULL, 0, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
char *env, *p;
|
char *env, *p;
|
||||||
@@ -907,14 +972,22 @@ static const struct mfx_option longopts[] =
|
|||||||
static void first_options(int argc, char **argv)
|
static void first_options(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
int n = argc;
|
||||||
|
|
||||||
for (i = 1; i < argc; i++)
|
for (i = 1; i < n; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(argv[i],"--") == 0)
|
||||||
|
{
|
||||||
|
n = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (strcmp(argv[i],"--version") == 0)
|
if (strcmp(argv[i],"--version") == 0)
|
||||||
do_option('V'+256, argv[i]);
|
do_option('V'+256, argv[i]);
|
||||||
for (i = 1; i < argc; i++)
|
}
|
||||||
|
for (i = 1; i < n; i++)
|
||||||
if (strcmp(argv[i],"--help") == 0)
|
if (strcmp(argv[i],"--help") == 0)
|
||||||
do_option('h'+256, argv[i]);
|
do_option('h'+256, argv[i]);
|
||||||
for (i = 1; i < argc; i++)
|
for (i = 1; i < n; i++)
|
||||||
if (strcmp(argv[i],"--no-env") == 0)
|
if (strcmp(argv[i],"--no-env") == 0)
|
||||||
do_option(519, argv[i]);
|
do_option(519, argv[i]);
|
||||||
}
|
}
|
||||||
@@ -926,57 +999,101 @@ static void first_options(int argc, char **argv)
|
|||||||
|
|
||||||
void upx_sanity_check(void)
|
void upx_sanity_check(void)
|
||||||
{
|
{
|
||||||
assert(sizeof(char) == 1);
|
COMPILE_TIME_ASSERT(sizeof(char) == 1);
|
||||||
assert(sizeof(short) == 2);
|
COMPILE_TIME_ASSERT(sizeof(short) == 2);
|
||||||
assert(sizeof(int) == 4);
|
COMPILE_TIME_ASSERT(sizeof(int) == 4);
|
||||||
assert(sizeof(long) >= 4);
|
COMPILE_TIME_ASSERT(sizeof(long) >= 4);
|
||||||
assert(sizeof(void *) >= 4);
|
COMPILE_TIME_ASSERT(sizeof(void *) >= 4);
|
||||||
assert(sizeof(long) >= sizeof(void *));
|
COMPILE_TIME_ASSERT(sizeof(long) >= sizeof(void *));
|
||||||
assert(((size_t) -1) > 0);
|
|
||||||
assert(((ptrdiff_t) -1) < 0);
|
|
||||||
assert(((off_t) -1) < 0);
|
|
||||||
|
|
||||||
assert(sizeof(BE16) == 2);
|
COMPILE_TIME_ASSERT(sizeof(upx_int64l) >= 8);
|
||||||
assert(sizeof(BE32) == 4);
|
COMPILE_TIME_ASSERT(sizeof(upx_int64l) >= sizeof(long));
|
||||||
assert(sizeof(LE16) == 2);
|
COMPILE_TIME_ASSERT(sizeof(upx_int64l) == sizeof(upx_uint64l));
|
||||||
assert(sizeof(LE32) == 4);
|
|
||||||
|
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(off_t) >= sizeof(long));
|
||||||
|
COMPILE_TIME_ASSERT(((off_t) -1) < 0);
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(ptrdiff_t) >= sizeof(int));
|
||||||
|
COMPILE_TIME_ASSERT(((ptrdiff_t) -1) < 0);
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(size_t) >= sizeof(int));
|
||||||
|
COMPILE_TIME_ASSERT(((size_t) -1) > 0);
|
||||||
|
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(BE16) == 2);
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(BE32) == 4);
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(LE16) == 2);
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(LE32) == 4);
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
COMPILE_TIME_ASSERT(__alignof__(BE16) == 1);
|
||||||
|
COMPILE_TIME_ASSERT(__alignof__(BE32) == 1);
|
||||||
|
COMPILE_TIME_ASSERT(__alignof__(LE16) == 1);
|
||||||
|
COMPILE_TIME_ASSERT(__alignof__(LE32) == 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(__WATCOMC__)
|
||||||
struct align_assertion_1a_t
|
struct align_assertion_1a_t
|
||||||
{
|
{
|
||||||
struct foo_t {
|
struct foo_t {
|
||||||
char c1;
|
char c1;
|
||||||
LE16 v[4];
|
LE16 v[4];
|
||||||
} d[3];
|
} __attribute_packed;
|
||||||
};
|
foo_t d[3];
|
||||||
|
} __attribute_packed;
|
||||||
struct align_assertion_1b_t
|
struct align_assertion_1b_t
|
||||||
{
|
{
|
||||||
struct foo_t {
|
struct foo_t {
|
||||||
char c1;
|
char c1;
|
||||||
char v[4*2];
|
char v[4*2];
|
||||||
} d[3];
|
} __attribute_packed;
|
||||||
};
|
foo_t d[3];
|
||||||
|
} __attribute_packed;
|
||||||
struct align_assertion_2a_t
|
struct align_assertion_2a_t
|
||||||
{
|
{
|
||||||
struct foo_t {
|
struct foo_t {
|
||||||
char c1;
|
char c1;
|
||||||
LE32 v[4];
|
LE32 v[4];
|
||||||
} d[3];
|
} __attribute_packed;
|
||||||
};
|
foo_t d[3];
|
||||||
|
} __attribute_packed;
|
||||||
struct align_assertion_2b_t
|
struct align_assertion_2b_t
|
||||||
{
|
{
|
||||||
struct foo_t {
|
struct foo_t {
|
||||||
char c1;
|
char c1;
|
||||||
char v[4*4];
|
char v[4*4];
|
||||||
} d[3];
|
} __attribute_packed;
|
||||||
};
|
foo_t d[3];
|
||||||
|
} __attribute_packed;
|
||||||
|
|
||||||
//printf("%d\n", (int) sizeof(align_assertion_1a_t));
|
//printf("%d\n", (int) sizeof(align_assertion_1a_t));
|
||||||
//printf("%d\n", (int) sizeof(align_assertion_1b_t));
|
//printf("%d\n", (int) sizeof(align_assertion_1b_t));
|
||||||
//printf("%d\n", (int) sizeof(align_assertion_2a_t));
|
//printf("%d\n", (int) sizeof(align_assertion_2a_t));
|
||||||
//printf("%d\n", (int) sizeof(align_assertion_2b_t));
|
//printf("%d\n", (int) sizeof(align_assertion_2b_t));
|
||||||
assert(sizeof(align_assertion_1a_t) == sizeof(align_assertion_1b_t));
|
COMPILE_TIME_ASSERT(sizeof(align_assertion_1a_t) == sizeof(align_assertion_1b_t));
|
||||||
assert(sizeof(align_assertion_2a_t) == sizeof(align_assertion_2b_t));
|
COMPILE_TIME_ASSERT(sizeof(align_assertion_2a_t) == sizeof(align_assertion_2b_t));
|
||||||
assert(sizeof(align_assertion_1a_t) == 3*9);
|
COMPILE_TIME_ASSERT(sizeof(align_assertion_1a_t) == 3*9);
|
||||||
assert(sizeof(align_assertion_2a_t) == 3*17);
|
COMPILE_TIME_ASSERT(sizeof(align_assertion_2a_t) == 3*17);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(UPX_VERSION_STRING4) == 4 + 1);
|
||||||
|
assert(strlen(UPX_VERSION_STRING4) == 4);
|
||||||
|
assert(memcmp(UPX_VERSION_STRING4, UPX_VERSION_STRING, 4) == 0);
|
||||||
|
|
||||||
|
const unsigned char dd[4] = { 0xff, 0xfe, 0xfd, 0xfc };
|
||||||
|
assert(get_be16(dd) == 0xfffe);
|
||||||
|
assert(get_be16_signed(dd) == -2);
|
||||||
|
assert(get_be24(dd) == 0xfffefd);
|
||||||
|
assert(get_be24_signed(dd) == -259);
|
||||||
|
assert(get_be32(dd) == 0xfffefdfc);
|
||||||
|
assert(get_be32_signed(dd) == -66052);
|
||||||
|
assert(get_le16(dd) == 0xfeff);
|
||||||
|
assert(get_le16_signed(dd) == -257);
|
||||||
|
assert(get_le24(dd) == 0xfdfeff);
|
||||||
|
assert(get_le24_signed(dd) == -131329);
|
||||||
|
assert(get_le32(dd) == 0xfcfdfeff);
|
||||||
|
assert(get_le32_signed(dd) == -50462977);
|
||||||
|
assert(find_be16(dd, sizeof(dd), 0xfffe) == 0);
|
||||||
|
assert(find_le16(dd, sizeof(dd), 0xfeff) == 0);
|
||||||
|
assert(find_be32(dd, sizeof(dd), 0xfffefdfc) == 0);
|
||||||
|
assert(find_le32(dd, sizeof(dd), 0xfcfdfeff) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -990,19 +1107,24 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
static char default_argv0[] = "upx";
|
static char default_argv0[] = "upx";
|
||||||
int cmdline_cmd = CMD_NONE;
|
// int cmdline_cmd = CMD_NONE;
|
||||||
|
|
||||||
upx_sanity_check();
|
#if 0 && defined(__DJGPP__)
|
||||||
init_options(opt);
|
// LFN=n may cause problems with 2.03's _rename and mkdir under WinME
|
||||||
|
putenv("LFN=y");
|
||||||
#if defined(WITH_MSS)
|
|
||||||
MSS_DISABLE_LOG_OUTPUT;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__EMX__)
|
#if defined(__EMX__)
|
||||||
_response(&argc,&argv);
|
_response(&argc,&argv);
|
||||||
_wildcard(&argc,&argv);
|
_wildcard(&argc,&argv);
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(__MINT__)
|
||||||
|
__binmode(1);
|
||||||
|
__set_binmode(stdout, 0);
|
||||||
|
__set_binmode(stderr, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
upx_sanity_check();
|
||||||
|
init_options(opt);
|
||||||
|
|
||||||
if (!argv[0] || !argv[0][0])
|
if (!argv[0] || !argv[0][0])
|
||||||
argv[0] = default_argv0;
|
argv[0] = default_argv0;
|
||||||
@@ -1011,15 +1133,15 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
char *prog = fn_basename(argv0);
|
char *prog = fn_basename(argv0);
|
||||||
char *p;
|
char *p;
|
||||||
bool allupper = 1;
|
bool allupper = true;
|
||||||
for (p = prog; *p; p++)
|
for (p = prog; *p; p++)
|
||||||
if (islower((unsigned char)*p))
|
if (islower((unsigned char)*p))
|
||||||
allupper = 0;
|
allupper = false;
|
||||||
if (allupper)
|
if (allupper)
|
||||||
fn_strlwr(prog);
|
fn_strlwr(prog);
|
||||||
if (strlen(prog) > 4)
|
if (p - prog > 4)
|
||||||
{
|
{
|
||||||
p = prog + strlen(prog) - 4;
|
p -= 4;
|
||||||
if (fn_strcmp(p, ".exe") == 0 || fn_strcmp(p, ".ttp") == 0)
|
if (fn_strcmp(p, ".exe") == 0 || fn_strcmp(p, ".ttp") == 0)
|
||||||
*p = 0;
|
*p = 0;
|
||||||
}
|
}
|
||||||
@@ -1043,7 +1165,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(WITH_NRV)
|
#if defined(WITH_NRV)
|
||||||
if (nrv_init() != NRV_E_OK)
|
if (nrv_init() != NRV_E_OK || NRV_VERSION != nrv_version())
|
||||||
{
|
{
|
||||||
show_head();
|
show_head();
|
||||||
fprintf(stderr,"nrv_init() failed - check your NRV installation !\n");
|
fprintf(stderr,"nrv_init() failed - check your NRV installation !\n");
|
||||||
@@ -1067,7 +1189,7 @@ int main(int argc, char *argv[])
|
|||||||
assert(i <= argc);
|
assert(i <= argc);
|
||||||
|
|
||||||
set_term(0);
|
set_term(0);
|
||||||
cmdline_cmd = opt->cmd;
|
// cmdline_cmd = opt->cmd;
|
||||||
switch (opt->cmd)
|
switch (opt->cmd)
|
||||||
{
|
{
|
||||||
case CMD_NONE:
|
case CMD_NONE:
|
||||||
@@ -1106,7 +1228,6 @@ int main(int argc, char *argv[])
|
|||||||
// invalidate compression options
|
// invalidate compression options
|
||||||
opt->method = 0;
|
opt->method = 0;
|
||||||
opt->level = 0;
|
opt->level = 0;
|
||||||
opt->mem_level = 0;
|
|
||||||
memset(&opt->crp, 0xff, sizeof(opt->crp));
|
memset(&opt->crp, 0xff, sizeof(opt->crp));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1128,7 +1249,7 @@ int main(int argc, char *argv[])
|
|||||||
set_term(stdout);
|
set_term(stdout);
|
||||||
do_files(i,argc,argv);
|
do_files(i,argc,argv);
|
||||||
|
|
||||||
#if 1 && (UPX_VERSION < 0x012000)
|
#if 1 && (UPX_VERSION_HEX < 0x020000)
|
||||||
{
|
{
|
||||||
FILE *f = stdout;
|
FILE *f = stdout;
|
||||||
int fg = con_fg(f,FG_RED);
|
int fg = con_fg(f,FG_RED);
|
||||||
@@ -1136,7 +1257,7 @@ int main(int argc, char *argv[])
|
|||||||
fg = con_fg(f,fg);
|
fg = con_fg(f,fg);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if 1 && !defined(WITH_NRV)
|
#if 0 && !defined(WITH_NRV)
|
||||||
{
|
{
|
||||||
FILE *f = stdout;
|
FILE *f = stdout;
|
||||||
int fg = con_fg(f,FG_GREEN);
|
int fg = con_fg(f,FG_GREEN);
|
||||||
|
|||||||
+10
-20
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -44,11 +44,10 @@ MemBuffer::MemBuffer(unsigned size) :
|
|||||||
|
|
||||||
MemBuffer::~MemBuffer()
|
MemBuffer::~MemBuffer()
|
||||||
{
|
{
|
||||||
this->free();
|
this->dealloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MemBuffer::dealloc()
|
||||||
void MemBuffer::free()
|
|
||||||
{
|
{
|
||||||
if (alloc_ptr)
|
if (alloc_ptr)
|
||||||
::free(alloc_ptr);
|
::free(alloc_ptr);
|
||||||
@@ -69,17 +68,14 @@ unsigned MemBuffer::getSize() const
|
|||||||
|
|
||||||
void MemBuffer::alloc(unsigned size, unsigned base_offset)
|
void MemBuffer::alloc(unsigned size, unsigned base_offset)
|
||||||
{
|
{
|
||||||
#if 0
|
// NOTE: we don't automaticlly free a used buffer
|
||||||
this->free();
|
|
||||||
#else
|
|
||||||
// don't automaticlly free a used buffer
|
|
||||||
#endif
|
|
||||||
assert(alloc_ptr == NULL);
|
assert(alloc_ptr == NULL);
|
||||||
assert((int)size > 0);
|
assert((int)size > 0);
|
||||||
size = base_offset + size;
|
size = base_offset + size;
|
||||||
alloc_ptr = (unsigned char *) malloc(size);
|
alloc_ptr = (unsigned char *) malloc(size);
|
||||||
if (!alloc_ptr)
|
if (!alloc_ptr)
|
||||||
{
|
{
|
||||||
|
//throw bad_alloc();
|
||||||
throwCantPack("out of memory");
|
throwCantPack("out of memory");
|
||||||
//exit(1);
|
//exit(1);
|
||||||
}
|
}
|
||||||
@@ -96,20 +92,14 @@ void MemBuffer::alloc(unsigned size)
|
|||||||
|
|
||||||
void MemBuffer::allocForCompression(unsigned uncompressed_size)
|
void MemBuffer::allocForCompression(unsigned uncompressed_size)
|
||||||
{
|
{
|
||||||
// Idea:
|
assert((int)uncompressed_size > 0);
|
||||||
// We allocate the buffer at an offset of 4096 so
|
alloc(uncompressed_size + uncompressed_size/8 + 256, 0);
|
||||||
// that we could do an in-place decompression for
|
|
||||||
// verifying our overlap_overhead at the end
|
|
||||||
// of packing.
|
|
||||||
//
|
|
||||||
// See Packer::verifyOverlappingDecompression().
|
|
||||||
|
|
||||||
alloc(uncompressed_size + uncompressed_size/8 + 256, MAX_OVERLAP_OVERHEAD);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MemBuffer::allocForUncompression(unsigned uncompressed_size)
|
void MemBuffer::allocForUncompression(unsigned uncompressed_size)
|
||||||
{
|
{
|
||||||
|
assert((int)uncompressed_size > 0);
|
||||||
//alloc(uncompressed_size + 3 + 512, 0); // 512 safety bytes
|
//alloc(uncompressed_size + 3 + 512, 0); // 512 safety bytes
|
||||||
alloc(uncompressed_size + 3, 0); // 3 bytes for asm_fast decompresion
|
alloc(uncompressed_size + 3, 0); // 3 bytes for asm_fast decompresion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ public:
|
|||||||
void allocForCompression(unsigned uncompressed_size);
|
void allocForCompression(unsigned uncompressed_size);
|
||||||
void allocForUncompression(unsigned uncompressed_size);
|
void allocForUncompression(unsigned uncompressed_size);
|
||||||
|
|
||||||
void free();
|
void dealloc();
|
||||||
|
|
||||||
const unsigned char *getBuf() const { return ptr; }
|
const unsigned char *getBuf() const { return ptr; }
|
||||||
unsigned getSize() const;
|
unsigned getSize() const;
|
||||||
@@ -52,11 +52,13 @@ public:
|
|||||||
operator unsigned char * () { return ptr; }
|
operator unsigned char * () { return ptr; }
|
||||||
//operator const unsigned char * () const { return ptr; }
|
//operator const unsigned char * () const { return ptr; }
|
||||||
|
|
||||||
enum { MAX_OVERLAP_OVERHEAD = 4096 };
|
void *getVoidPtr() { return (void *) ptr; }
|
||||||
|
const void *getVoidPtr() const { return (const void *) ptr; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void alloc(unsigned size, unsigned base_offset);
|
void alloc(unsigned size, unsigned base_offset);
|
||||||
|
|
||||||
|
protected:
|
||||||
unsigned char *ptr;
|
unsigned char *ptr;
|
||||||
unsigned char *alloc_ptr;
|
unsigned char *alloc_ptr;
|
||||||
unsigned alloc_size;
|
unsigned alloc_size;
|
||||||
@@ -67,13 +69,16 @@ private:
|
|||||||
MemBuffer& operator= (MemBuffer const &); // { return *this; }
|
MemBuffer& operator= (MemBuffer const &); // { return *this; }
|
||||||
|
|
||||||
// disable dynamic allocation
|
// disable dynamic allocation
|
||||||
|
#ifndef new
|
||||||
static void *operator new (size_t); // {}
|
static void *operator new (size_t); // {}
|
||||||
static void *operator new[] (size_t); // {}
|
static void *operator new[] (size_t); // {}
|
||||||
|
#endif
|
||||||
|
#ifndef delete
|
||||||
//static void operator delete (void *) {}
|
//static void operator delete (void *) {}
|
||||||
//static void operator delete[] (void *) {}
|
//static void operator delete[] (void *) {}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* already included */
|
#endif /* already included */
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+4
-5
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -73,7 +73,6 @@ static void pr_print(bool c, const char *msg)
|
|||||||
|
|
||||||
static void pr_error(const char *iname, const char *msg, bool is_warning)
|
static void pr_error(const char *iname, const char *msg, bool is_warning)
|
||||||
{
|
{
|
||||||
set_ec(EXIT_ERROR);
|
|
||||||
fflush(stdout); fflush(stderr);
|
fflush(stdout); fflush(stderr);
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
buf[0] = 0;
|
buf[0] = 0;
|
||||||
@@ -146,7 +145,7 @@ void printWarn(const char *iname, const char *format, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void printUnhandledException(const char *iname, const exception *e)
|
void printUnhandledException(const char *iname, const std::exception *e)
|
||||||
{
|
{
|
||||||
if (e)
|
if (e)
|
||||||
printErr(iname,"unhandled exception: %s\n", prettyName(e->what()));
|
printErr(iname,"unhandled exception: %s\n", prettyName(e->what()));
|
||||||
|
|||||||
+142
@@ -0,0 +1,142 @@
|
|||||||
|
/* options.h --
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __UPX_OPTIONS_H
|
||||||
|
#define __UPX_OPTIONS_H
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// globals
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
// options - command
|
||||||
|
enum {
|
||||||
|
CMD_NONE,
|
||||||
|
CMD_COMPRESS, CMD_DECOMPRESS, CMD_TEST, CMD_LIST, CMD_FILEINFO,
|
||||||
|
CMD_HELP, CMD_LICENSE, CMD_VERSION
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct options_t {
|
||||||
|
int cmd;
|
||||||
|
|
||||||
|
// compression options
|
||||||
|
int method;
|
||||||
|
int level; // compression level 1..10
|
||||||
|
int filter; // preferred filter from Packer::getFilters()
|
||||||
|
bool all_methods; // try all available compression methods ?
|
||||||
|
bool all_filters; // try all available filters ?
|
||||||
|
|
||||||
|
// other options
|
||||||
|
int backup;
|
||||||
|
int console;
|
||||||
|
int debug;
|
||||||
|
int force;
|
||||||
|
int info_mode;
|
||||||
|
bool ignorewarn;
|
||||||
|
bool no_env;
|
||||||
|
bool no_progress;
|
||||||
|
const char *output_name;
|
||||||
|
int small;
|
||||||
|
int verbose;
|
||||||
|
bool to_stdout;
|
||||||
|
|
||||||
|
// overlay handling
|
||||||
|
enum {
|
||||||
|
SKIP_OVERLAY = 0,
|
||||||
|
COPY_OVERLAY = 1,
|
||||||
|
STRIP_OVERLAY = 2
|
||||||
|
};
|
||||||
|
int overlay;
|
||||||
|
|
||||||
|
// compression runtime parameters - see struct ucl_compress_config_t
|
||||||
|
struct {
|
||||||
|
upx_uint max_offset;
|
||||||
|
upx_uint max_match;
|
||||||
|
int s_level;
|
||||||
|
int h_level;
|
||||||
|
int p_level;
|
||||||
|
int c_flags;
|
||||||
|
upx_uint m_size;
|
||||||
|
} crp;
|
||||||
|
|
||||||
|
// CPU
|
||||||
|
enum {
|
||||||
|
CPU_DEFAULT = 0,
|
||||||
|
CPU_8086 = 1,
|
||||||
|
CPU_286 = 2,
|
||||||
|
CPU_386 = 3,
|
||||||
|
CPU_486 = 4,
|
||||||
|
CPU_586 = 5,
|
||||||
|
CPU_686 = 6
|
||||||
|
};
|
||||||
|
int cpu;
|
||||||
|
|
||||||
|
// options for various executable formats
|
||||||
|
struct {
|
||||||
|
bool force_stub;
|
||||||
|
bool no_reloc;
|
||||||
|
} dos;
|
||||||
|
struct {
|
||||||
|
bool coff;
|
||||||
|
} djgpp2;
|
||||||
|
struct {
|
||||||
|
bool no_align;
|
||||||
|
} ps1;
|
||||||
|
struct {
|
||||||
|
bool split_segments;
|
||||||
|
} tos;
|
||||||
|
struct {
|
||||||
|
unsigned blocksize;
|
||||||
|
bool force_execve; // force the linux/386 execve format
|
||||||
|
bool ptinterp; // is PT_INTERP, so don't adjust auxv_t
|
||||||
|
enum { SCRIPT_MAX = 32 };
|
||||||
|
const char *script_name;
|
||||||
|
} unix;
|
||||||
|
struct {
|
||||||
|
bool le;
|
||||||
|
} wcle;
|
||||||
|
struct {
|
||||||
|
int compress_exports;
|
||||||
|
int compress_icons;
|
||||||
|
int compress_resources;
|
||||||
|
signed char compress_rt[25]; // 25 == RT_LAST
|
||||||
|
int strip_relocs;
|
||||||
|
} w32pe;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct options_t * volatile opt;
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* already included */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
vi:ts=4:et
|
||||||
|
*/
|
||||||
|
|
||||||
+40
-44
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -35,8 +35,6 @@
|
|||||||
static const
|
static const
|
||||||
#include "stub/l_com.h"
|
#include "stub/l_com.h"
|
||||||
|
|
||||||
#define STACKSIZE 0x60
|
|
||||||
|
|
||||||
//#define TESTING
|
//#define TESTING
|
||||||
|
|
||||||
|
|
||||||
@@ -44,22 +42,27 @@ static const
|
|||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
int PackCom::getCompressionMethod() const
|
const int *PackCom::getCompressionMethods(int method, int level) const
|
||||||
{
|
{
|
||||||
if (M_IS_NRV2B(opt->method))
|
static const int m_nrv2b[] = { M_NRV2B_LE16, -1 };
|
||||||
return M_NRV2B_LE16;
|
if (M_IS_NRV2B(method))
|
||||||
|
return m_nrv2b;
|
||||||
#if 0
|
#if 0
|
||||||
// NOT IMPLEMENTED
|
// NOT IMPLEMENTED
|
||||||
if (M_IS_NRV2D(opt->method))
|
static const int m_nrv2d[] = { M_NRV2D_LE16, -1 };
|
||||||
return M_NRV2D_LE16;
|
if (M_IS_NRV2D(method))
|
||||||
|
return m_nrv2d;
|
||||||
#endif
|
#endif
|
||||||
return M_NRV2B_LE16;
|
UNUSED(level);
|
||||||
|
return m_nrv2b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const int *PackCom::getFilters() const
|
const int *PackCom::getFilters() const
|
||||||
{
|
{
|
||||||
static const int filters[] = { 0x06, 0x03, 0x04, 0x01, 0x05, 0x02, -1 };
|
static const int filters[] = {
|
||||||
|
0x06, 0x03, 0x04, 0x01, 0x05, 0x02,
|
||||||
|
-1 };
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,14 +75,13 @@ bool PackCom::canPack()
|
|||||||
{
|
{
|
||||||
unsigned char buf[128];
|
unsigned char buf[128];
|
||||||
|
|
||||||
fi->readx(buf,128);
|
fi->readx(buf, sizeof(buf));
|
||||||
if (memcmp(buf,"MZ",2) == 0 || memcmp(buf,"ZM",2) == 0 // .exe
|
if (memcmp(buf,"MZ",2) == 0 || memcmp(buf,"ZM",2) == 0 // .exe
|
||||||
|| memcmp (buf,"\xff\xff\xff\xff",4) == 0) // .sys
|
|| memcmp (buf,"\xff\xff\xff\xff",4) == 0) // .sys
|
||||||
return false;
|
return false;
|
||||||
if (!fn_has_ext(fi->getName(),"com"))
|
if (!fn_has_ext(fi->getName(),"com"))
|
||||||
return false;
|
return false;
|
||||||
if (find_le32(buf,128,UPX_MAGIC_LE32) >= 0)
|
checkAlreadyPacked(buf, sizeof(buf));
|
||||||
throwAlreadyPacked();
|
|
||||||
if (file_size < 1024)
|
if (file_size < 1024)
|
||||||
throwCantPack("file is too small");
|
throwCantPack("file is too small");
|
||||||
if (file_size > 0xFF00)
|
if (file_size > 0xFF00)
|
||||||
@@ -94,7 +96,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");
|
||||||
@@ -102,9 +104,12 @@ 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)
|
unsigned stacksize = 0x60;
|
||||||
throwNotCompressible();
|
if (upper_end + stacksize > 0xfffe)
|
||||||
|
stacksize = 0x56;
|
||||||
|
if (upper_end + stacksize > 0xfffe)
|
||||||
|
throwCantPack("file is too big for dos/com");
|
||||||
|
|
||||||
if (filter_id)
|
if (filter_id)
|
||||||
{
|
{
|
||||||
@@ -116,11 +121,11 @@ void PackCom::patchLoader(OutputFile *fo,
|
|||||||
|
|
||||||
// NOTE: Depends on: decompr_start == cutpoint+1 !!!
|
// NOTE: Depends on: decompr_start == cutpoint+1 !!!
|
||||||
patch_le16(loader,e_len,"JM",upper_end - 0xff - d_len - getLoaderSection("UPX1HEAD"));
|
patch_le16(loader,e_len,"JM",upper_end - 0xff - d_len - getLoaderSection("UPX1HEAD"));
|
||||||
loader[getLoaderSection("COMSUBSI") - 1] = (upx_byte) -e_len;
|
loader[getLoaderSectionStart("COMSUBSI") - 1] = (upx_byte) -e_len;
|
||||||
patch_le16(loader,e_len,"DI",upper_end);
|
patch_le16(loader,e_len,"DI",upper_end);
|
||||||
patch_le16(loader,e_len,"SI",ph.c_len + lsize + 0x100);
|
patch_le16(loader,e_len,"SI",ph.c_len + lsize + 0x100);
|
||||||
patch_le16(loader,e_len,"CX",ph.c_len + lsize);
|
patch_le16(loader,e_len,"CX",ph.c_len + lsize);
|
||||||
patch_le16(loader,e_len,"SP",upper_end + STACKSIZE);
|
patch_le16(loader,e_len,"SP",upper_end + stacksize);
|
||||||
|
|
||||||
// write loader + compressed file
|
// write loader + compressed file
|
||||||
fo->write(loader,e_len); // entry
|
fo->write(loader,e_len); // entry
|
||||||
@@ -136,19 +141,23 @@ void PackCom::patchLoader(OutputFile *fo,
|
|||||||
|
|
||||||
int PackCom::buildLoader(const Filter *ft)
|
int PackCom::buildLoader(const Filter *ft)
|
||||||
{
|
{
|
||||||
const int filter_id = ft->id;
|
|
||||||
initLoader(nrv2b_loader,sizeof(nrv2b_loader));
|
initLoader(nrv2b_loader,sizeof(nrv2b_loader));
|
||||||
addLoader("COMMAIN1""COMSUBSI",
|
addLoader("COMMAIN1""COMSUBSI",
|
||||||
filter_id ? "COMCALLT" : "",
|
ph.first_offset_found == 1 ? "COMSBBBP" : "",
|
||||||
|
"COMPSHDI",
|
||||||
|
ft->id ? "COMCALLT" : "",
|
||||||
"COMMAIN2""UPX1HEAD""COMCUTPO""NRV2B160",
|
"COMMAIN2""UPX1HEAD""COMCUTPO""NRV2B160",
|
||||||
filter_id ? "NRVDDONE" : "NRVDRETU",
|
ft->id ? "NRVDDONE" : "NRVDRETU",
|
||||||
"NRVDECO1",
|
"NRVDECO1",
|
||||||
ph.max_offset_found <= 0xd00 ? "NRVLED00" : "NRVGTD00",
|
ph.max_offset_found <= 0xd00 ? "NRVLED00" : "NRVGTD00",
|
||||||
"NRVDECO2""NRV2B169",
|
"NRVDECO2""NRV2B169",
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
if (filter_id)
|
if (ft->id)
|
||||||
addFilter16(filter_id);
|
{
|
||||||
|
assert(ft->calls > 0);
|
||||||
|
addFilter16(ft->id);
|
||||||
|
}
|
||||||
return getLoaderSize();
|
return getLoaderSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,35 +201,22 @@ void PackCom::pack(OutputFile *fo)
|
|||||||
|
|
||||||
// prepare packheader
|
// prepare packheader
|
||||||
ph.u_len = file_size;
|
ph.u_len = file_size;
|
||||||
ph.filter = 0;
|
|
||||||
// prepare filter
|
// prepare filter
|
||||||
Filter ft(opt->level);
|
Filter ft(ph.level);
|
||||||
ft.addvalue = getCallTrickOffset();
|
ft.addvalue = getCallTrickOffset();
|
||||||
// prepare other settings
|
// compress
|
||||||
const unsigned overlap_range = ph.u_len < 0xFE00 - ft.addvalue ? 32 : 0;
|
const unsigned overlap_range = ph.u_len < 0xFE00 - ft.addvalue ? 32 : 0;
|
||||||
unsigned overlapoh;
|
compressWithFilters(&ft, overlap_range);
|
||||||
|
|
||||||
int strategy = -1; // try the first working filter
|
|
||||||
if (opt->filter >= 0 && isValidFilter(opt->filter))
|
|
||||||
// try opt->filter or 0 if that fails
|
|
||||||
strategy = -2;
|
|
||||||
else if (opt->all_filters || opt->level > 9)
|
|
||||||
// choose best from all available filters
|
|
||||||
strategy = 0;
|
|
||||||
else if (opt->level == 9)
|
|
||||||
// choose best from the first 4 filters
|
|
||||||
strategy = 4;
|
|
||||||
compressWithFilters(&ft, &overlapoh, 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();
|
||||||
|
|
||||||
// finally check the compression ratio
|
// finally check the compression ratio
|
||||||
if (!checkFinalCompressionRatio(fo))
|
if (!checkFinalCompressionRatio(fo))
|
||||||
|
|||||||
+6
-6
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -39,10 +39,10 @@ class PackCom : public Packer
|
|||||||
typedef Packer super;
|
typedef Packer super;
|
||||||
public:
|
public:
|
||||||
PackCom(InputFile *f) : super(f) { }
|
PackCom(InputFile *f) : super(f) { }
|
||||||
virtual int getVersion() const { return 11; }
|
virtual int getVersion() const { return 13; }
|
||||||
virtual int getFormat() const { return UPX_F_DOS_COM; }
|
virtual int getFormat() const { return UPX_F_DOS_COM; }
|
||||||
virtual const char *getName() const { return "dos/com"; }
|
virtual const char *getName() const { return "dos/com"; }
|
||||||
virtual int getCompressionMethod() const;
|
virtual const int *getCompressionMethods(int method, int level) const;
|
||||||
virtual const int *getFilters() const;
|
virtual const int *getFilters() const;
|
||||||
|
|
||||||
virtual void pack(OutputFile *fo);
|
virtual void pack(OutputFile *fo);
|
||||||
@@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+57
-72
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,9 +22,10 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
@@ -45,28 +46,41 @@ static const
|
|||||||
PackDjgpp2::PackDjgpp2(InputFile *f) :
|
PackDjgpp2::PackDjgpp2(InputFile *f) :
|
||||||
super(f), coff_offset(0)
|
super(f), coff_offset(0)
|
||||||
{
|
{
|
||||||
assert(sizeof(coff_hdr) == 0xa8);
|
COMPILE_TIME_ASSERT(sizeof(external_scnhdr_t) == 40);
|
||||||
assert(sizeof(stubify_stub) == 2048);
|
COMPILE_TIME_ASSERT(sizeof(coff_header_t) == 0xa8);
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(stubify_stub) == 2048);
|
||||||
|
#if defined(STUBIFY_STUB_ADLER32)
|
||||||
|
//printf("0x%08x\n", upx_adler32(stubify_stub, sizeof(stubify_stub)));
|
||||||
|
assert(upx_adler32(stubify_stub, sizeof(stubify_stub)) == STUBIFY_STUB_ADLER32);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int PackDjgpp2::getCompressionMethod() const
|
const int *PackDjgpp2::getCompressionMethods(int method, int level) const
|
||||||
{
|
{
|
||||||
if (M_IS_NRV2B(opt->method))
|
return Packer::getDefaultCompressionMethods_le32(method, level);
|
||||||
return M_NRV2B_LE32;
|
|
||||||
if (M_IS_NRV2D(opt->method))
|
|
||||||
return M_NRV2D_LE32;
|
|
||||||
return opt->level > 1 && file_size >= 512*1024 ? M_NRV2D_LE32 : M_NRV2B_LE32;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const int *PackDjgpp2::getFilters() const
|
const int *PackDjgpp2::getFilters() const
|
||||||
{
|
{
|
||||||
static const int filters[] = { 0x26, 0x24, 0x11, 0x14, 0x13, 0x16,
|
static const int filters[] = {
|
||||||
0x25, 0x15, 0x12, -1 };
|
0x26, 0x24, 0x11, 0x14, 0x13, 0x16, 0x25, 0x15, 0x12,
|
||||||
|
-1 };
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
@@ -127,7 +141,7 @@ static bool is_dlm(InputFile *fi, long coff_offset)
|
|||||||
fi->readx(buf,4);
|
fi->readx(buf,4);
|
||||||
if (memcmp(buf,"DLMF",4) == 0)
|
if (memcmp(buf,"DLMF",4) == 0)
|
||||||
return true;
|
return true;
|
||||||
} catch (IOException&) {
|
} catch (const IOException&) {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -136,29 +150,31 @@ static bool is_dlm(InputFile *fi, long coff_offset)
|
|||||||
static void handle_allegropak(InputFile *fi, OutputFile *fo)
|
static void handle_allegropak(InputFile *fi, OutputFile *fo)
|
||||||
{
|
{
|
||||||
unsigned char buf[0x4000];
|
unsigned char buf[0x4000];
|
||||||
unsigned pfsize=0, ic;
|
int pfsize = 0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fi->seek(-8, SEEK_END);
|
fi->seek(-8, SEEK_END);
|
||||||
fi->readx(buf, 8);
|
fi->readx(buf, 8);
|
||||||
if (memcmp(buf, "slh+", 4) != 0)
|
if (memcmp(buf, "slh+", 4) != 0)
|
||||||
return;
|
return;
|
||||||
pfsize = get_be32(buf+4);
|
pfsize = get_be32_signed(buf+4);
|
||||||
fi->seek(-(off_t)pfsize,SEEK_END);
|
if (pfsize <= 8 || pfsize >= fi->st.st_size)
|
||||||
} catch (IOException&) {
|
return;
|
||||||
|
fi->seek(-pfsize, SEEK_END);
|
||||||
|
} catch (const IOException&) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while (pfsize)
|
while (pfsize > 0)
|
||||||
{
|
{
|
||||||
ic = pfsize < sizeof(buf) ? pfsize : sizeof(buf);
|
const int len = UPX_MIN(pfsize, (int)sizeof(buf));
|
||||||
fi->readx(buf,ic);
|
fi->readx(buf, len);
|
||||||
fo->write(buf,ic);
|
fo->write(buf, len);
|
||||||
pfsize -= ic;
|
pfsize -= len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PackDjgpp2::readFileHeader()
|
int PackDjgpp2::readFileHeader()
|
||||||
{
|
{
|
||||||
unsigned char hdr[0x1c];
|
unsigned char hdr[0x1c];
|
||||||
unsigned char magic[8];
|
unsigned char magic[8];
|
||||||
@@ -173,7 +189,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 +200,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -257,6 +273,8 @@ void PackDjgpp2::pack(OutputFile *fo)
|
|||||||
const unsigned hdrsize = 20 + 28 + (40 * coff_hdr.f_nscns);
|
const unsigned hdrsize = 20 + 28 + (40 * coff_hdr.f_nscns);
|
||||||
if (hdrsize < sizeof(coff_hdr) || hdrsize > tpos)
|
if (hdrsize < sizeof(coff_hdr) || hdrsize > tpos)
|
||||||
throwCantPack("coff header error");
|
throwCantPack("coff header error");
|
||||||
|
if (hdrsize > (tpos & 0x1ff))
|
||||||
|
throwCantPack("unsupported coff header");
|
||||||
|
|
||||||
ibuf.alloc(usize);
|
ibuf.alloc(usize);
|
||||||
obuf.allocForCompression(usize);
|
obuf.allocForCompression(usize);
|
||||||
@@ -267,59 +285,26 @@ void PackDjgpp2::pack(OutputFile *fo)
|
|||||||
fi->seek(coff_offset+tpos,SEEK_SET);
|
fi->seek(coff_offset+tpos,SEEK_SET);
|
||||||
fi->readx(ibuf + (tpos & 0x1ff),size);
|
fi->readx(ibuf + (tpos & 0x1ff),size);
|
||||||
|
|
||||||
#if 0
|
|
||||||
// filter
|
|
||||||
Filter ft(opt->level);
|
|
||||||
tryFilters(&ft, ibuf, usize - data->size, text->vaddr & ~0x1ff);
|
|
||||||
|
|
||||||
// compress
|
|
||||||
ph.filter = ft.id;
|
|
||||||
ph.filter_cto = ft.cto;
|
|
||||||
ph.u_len = usize;
|
|
||||||
if (!compress(ibuf,obuf))
|
|
||||||
throwNotCompressible();
|
|
||||||
|
|
||||||
unsigned overlapoh = findOverlapOverhead(obuf,ibuf,512);
|
|
||||||
overlapoh = (overlapoh + 0x3ff) & ~0x1ff;
|
|
||||||
|
|
||||||
// verify filter
|
|
||||||
ft.verifyUnfilter();
|
|
||||||
#else
|
|
||||||
// new version using compressWithFilters()
|
|
||||||
|
|
||||||
// prepare packheader
|
// prepare packheader
|
||||||
ph.u_len = usize;
|
ph.u_len = usize;
|
||||||
ph.filter = 0;
|
|
||||||
// prepare filter
|
// prepare filter
|
||||||
Filter ft(opt->level);
|
Filter ft(ph.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
|
// compress
|
||||||
const unsigned overlap_range = 512;
|
compressWithFilters(&ft, 512);
|
||||||
unsigned overlapoh;
|
|
||||||
|
|
||||||
int strategy = -1; // try the first working filter
|
|
||||||
if (opt->filter >= 0 && isValidFilter(opt->filter))
|
|
||||||
// try opt->filter or 0 if that fails
|
|
||||||
strategy = -2;
|
|
||||||
else if (opt->all_filters)
|
|
||||||
// choose best from all available filters
|
|
||||||
strategy = 0;
|
|
||||||
compressWithFilters(&ft, &overlapoh, overlap_range, strategy);
|
|
||||||
overlapoh = (overlapoh + 0x3ff) & ~0x1ff;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// patch coff header #2
|
// patch coff header #2
|
||||||
const unsigned lsize = getLoaderSize();
|
const unsigned lsize = getLoaderSize();
|
||||||
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
|
||||||
@@ -330,7 +315,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);
|
||||||
@@ -338,8 +323,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);
|
||||||
@@ -356,7 +341,7 @@ void PackDjgpp2::pack(OutputFile *fo)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
verifyOverlappingDecompression(&obuf, overlapoh);
|
verifyOverlappingDecompression();
|
||||||
|
|
||||||
// handle overlay
|
// handle overlay
|
||||||
// FIXME: only Allegro pakfiles are supported
|
// FIXME: only Allegro pakfiles are supported
|
||||||
|
|||||||
+16
-9
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -40,10 +40,10 @@ class PackDjgpp2 : public Packer
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
PackDjgpp2(InputFile *f);
|
PackDjgpp2(InputFile *f);
|
||||||
virtual int getVersion() const { return 11; }
|
virtual int getVersion() const { return 13; }
|
||||||
virtual int getFormat() const { return UPX_F_DJGPP2_COFF; }
|
virtual int getFormat() const { return UPX_F_DJGPP2_COFF; }
|
||||||
virtual const char *getName() const { return "djgpp2/coff"; }
|
virtual const char *getName() const { return "djgpp2/coff"; }
|
||||||
virtual int getCompressionMethod() const;
|
virtual const int *getCompressionMethods(int method, int level) const;
|
||||||
virtual const int *getFilters() const;
|
virtual const int *getFilters() const;
|
||||||
|
|
||||||
virtual void pack(OutputFile *fo);
|
virtual void pack(OutputFile *fo);
|
||||||
@@ -53,8 +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 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;
|
||||||
|
|
||||||
@@ -66,7 +71,8 @@ protected:
|
|||||||
LE32 scnptr;
|
LE32 scnptr;
|
||||||
char misc[12]; // relptr, lnnoptr, nreloc, nlnno
|
char misc[12]; // relptr, lnnoptr, nreloc, nlnno
|
||||||
char __[4]; // flags
|
char __[4]; // flags
|
||||||
};
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
struct coff_header_t
|
struct coff_header_t
|
||||||
{
|
{
|
||||||
@@ -90,11 +96,12 @@ protected:
|
|||||||
|
|
||||||
// section headers
|
// section headers
|
||||||
external_scnhdr_t sh[3];
|
external_scnhdr_t sh[3];
|
||||||
} coff_hdr;
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
|
coff_header_t coff_hdr;
|
||||||
external_scnhdr_t *text,*data,*bss;
|
external_scnhdr_t *text,*data,*bss;
|
||||||
|
|
||||||
bool readFileHeader();
|
|
||||||
void stripDebug();
|
void stripDebug();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+31
-10
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -51,7 +51,8 @@ struct Elf_LE32_Ehdr
|
|||||||
LE16 e_shentsize; /* Section header table entry size */
|
LE16 e_shentsize; /* Section header table entry size */
|
||||||
LE16 e_shnum; /* Section header table entry count */
|
LE16 e_shnum; /* Section header table entry count */
|
||||||
LE16 e_shstrndx; /* Section header string table index */
|
LE16 e_shstrndx; /* Section header string table index */
|
||||||
};
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
|
|
||||||
// Program segment header.
|
// Program segment header.
|
||||||
@@ -65,19 +66,39 @@ struct Elf_LE32_Phdr
|
|||||||
LE32 p_memsz; /* Segment size in memory */
|
LE32 p_memsz; /* Segment size in memory */
|
||||||
LE32 p_flags; /* Segment flags */
|
LE32 p_flags; /* Segment flags */
|
||||||
LE32 p_align; /* Segment alignment */
|
LE32 p_align; /* Segment alignment */
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Values for p_type
|
// Values for p_type
|
||||||
#define PT_LOAD 1 /* Loadable program segment */
|
enum {
|
||||||
|
PT_LOAD = 1, /* Loadable program segment */
|
||||||
|
PT_DYNAMIC = 2, /* Dynamic linking information */
|
||||||
|
PT_PHDR = 6 /* Entry for header table itself */
|
||||||
|
};
|
||||||
|
|
||||||
// Values for p_flags
|
// Values for p_flags
|
||||||
#define PF_X (1 << 0) /* Segment is executable */
|
enum { PF_X = (1 << 0) }; /* Segment is executable */
|
||||||
#define PF_W (1 << 1) /* Segment is writable */
|
enum { PF_W = (1 << 1) }; /* Segment is writable */
|
||||||
#define PF_R (1 << 2) /* Segment is readable */
|
enum { PF_R = (1 << 2) }; /* Segment is readable */
|
||||||
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
|
|
||||||
|
struct Elf_LE32_Dyn
|
||||||
|
{
|
||||||
|
LE32 d_tag;
|
||||||
|
LE32 d_val;
|
||||||
|
|
||||||
|
enum { // tags
|
||||||
|
DT_NULL = 0, /* End flag */
|
||||||
|
DT_NEEDED = 1, /* Name of needed library */
|
||||||
|
DT_STRTAB = 5, /* String table */
|
||||||
|
DT_STRSZ = 10 /* Sizeof string table */
|
||||||
|
};
|
||||||
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
#endif /* already included */
|
#endif /* already included */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
vi:ts=4:et
|
vi:ts=4:et
|
||||||
*/
|
*/
|
||||||
|
|||||||
+179
@@ -0,0 +1,179 @@
|
|||||||
|
/* p_elks.cpp --
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "conf.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
#include "file.h"
|
||||||
|
#include "filter.h"
|
||||||
|
#include "packer.h"
|
||||||
|
#include "p_vmlinz.h"
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
static const
|
||||||
|
#include "stub/l_vmlinz.h"
|
||||||
|
|
||||||
|
// from elks-0.0.83/Documentation/boot.txt
|
||||||
|
static const unsigned kernel_entry = 0x100000;
|
||||||
|
static const unsigned stack_during_uncompression = 0x90000;
|
||||||
|
static const unsigned zimage_offset = 0x1000;
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
const int *PackElks8086::getCompressionMethods(int method, int level) const
|
||||||
|
{
|
||||||
|
return Packer::getDefaultCompressionMethods_8(method, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const int *PackElks8086::getFilters() const
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// common util routines
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
int PackElks8086::decompressKernel()
|
||||||
|
{
|
||||||
|
// not used
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PackElks8086::readKernel()
|
||||||
|
{
|
||||||
|
int klen = file_size - setup_size;
|
||||||
|
fi->seek(0, SEEK_SET);
|
||||||
|
|
||||||
|
setup_buf.alloc(setup_size);
|
||||||
|
fi->readx(setup_buf, setup_size);
|
||||||
|
|
||||||
|
ibuf.alloc(klen);
|
||||||
|
fi->readx(ibuf, klen);
|
||||||
|
|
||||||
|
obuf.allocForCompression(klen);
|
||||||
|
|
||||||
|
ph.u_len = klen;
|
||||||
|
ph.filter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
int PackElks8086::buildLoader(const Filter *ft)
|
||||||
|
{
|
||||||
|
// prepare loader
|
||||||
|
initLoader(nrv_loader, sizeof(nrv_loader));
|
||||||
|
// FIXME
|
||||||
|
UNUSED(ft);
|
||||||
|
return getLoaderSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PackElks8086::pack(OutputFile *fo)
|
||||||
|
{
|
||||||
|
readKernel();
|
||||||
|
|
||||||
|
// prepare filter
|
||||||
|
Filter ft(ph.level);
|
||||||
|
ft.buf_len = ph.u_len;
|
||||||
|
ft.addvalue = kernel_entry;
|
||||||
|
// compress
|
||||||
|
compressWithFilters(&ft, overlap_range);
|
||||||
|
|
||||||
|
const unsigned lsize = getLoaderSize();
|
||||||
|
MemBuffer loader(lsize);
|
||||||
|
memcpy(loader, getLoader(), lsize);
|
||||||
|
|
||||||
|
patchPackHeader(loader, lsize);
|
||||||
|
#if 0
|
||||||
|
// FIXME
|
||||||
|
patchFilter32(loader, lsize, &ft);
|
||||||
|
patch_le32(loader, lsize, "ESI1", zimage_offset + lsize);
|
||||||
|
patch_le32(loader, lsize, "KEIP", kernel_entry);
|
||||||
|
patch_le32(loader, lsize, "STAK", stack_during_uncompression);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
boot_sect_t * const bs = (boot_sect_t *) ((unsigned char *) setup_buf);
|
||||||
|
bs->sys_size = ALIGN_UP(lsize + ph.c_len, 16) / 16;
|
||||||
|
|
||||||
|
fo->write(setup_buf, setup_buf.getSize());
|
||||||
|
fo->write(loader, lsize);
|
||||||
|
fo->write(obuf, ph.c_len);
|
||||||
|
#if 0
|
||||||
|
printf("%-13s: setup : %8ld bytes\n", getName(), (long) setup_buf.getSize());
|
||||||
|
printf("%-13s: loader : %8ld bytes\n", getName(), (long) lsize);
|
||||||
|
printf("%-13s: compressed : %8ld bytes\n", getName(), (long) ph.c_len);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// finally check the compression ratio
|
||||||
|
if (!checkFinalCompressionRatio(fo))
|
||||||
|
throwNotCompressible();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// unpack
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
int PackElks8086::canUnpack()
|
||||||
|
{
|
||||||
|
if (readFileHeader() != getFormat())
|
||||||
|
return false;
|
||||||
|
fi->seek(setup_size, SEEK_SET);
|
||||||
|
return readPackHeader(1024) ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PackElks8086::unpack(OutputFile *)
|
||||||
|
{
|
||||||
|
// no uncompression support for this format yet
|
||||||
|
|
||||||
|
// FIXME: but we could write the uncompressed "Image" image
|
||||||
|
|
||||||
|
throwCantUnpack("build a new kernel instead :-)");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* if 0 */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
vi:ts=4:et
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
+184
-149
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -39,6 +39,8 @@ static const
|
|||||||
#define MAXMATCH 0x2000
|
#define MAXMATCH 0x2000
|
||||||
#define MAXRELOCS (0x8000-MAXMATCH)
|
#define MAXRELOCS (0x8000-MAXMATCH)
|
||||||
|
|
||||||
|
#define DI_LIMIT 0xff00 // see the assembly why
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
//
|
||||||
@@ -47,18 +49,15 @@ static const
|
|||||||
PackExe::PackExe(InputFile *f) :
|
PackExe::PackExe(InputFile *f) :
|
||||||
super(f)
|
super(f)
|
||||||
{
|
{
|
||||||
assert(sizeof(exe_header_t) == 32);
|
COMPILE_TIME_ASSERT(sizeof(exe_header_t) == 32);
|
||||||
ih_exesize = ih_imagesize = ih_overlay = 0;
|
ih_exesize = ih_imagesize = ih_overlay = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int PackExe::getCompressionMethod() const
|
const int *PackExe::getCompressionMethods(int method, int level) const
|
||||||
{
|
{
|
||||||
if (M_IS_NRV2B(opt->method))
|
bool small = ih_imagesize <= 256*1024;
|
||||||
return M_NRV2B_8;
|
return Packer::getDefaultCompressionMethods_8(method, level, small);
|
||||||
if (M_IS_NRV2D(opt->method))
|
|
||||||
return M_NRV2D_8;
|
|
||||||
return opt->level > 1 && ih_imagesize >= 300000 ? M_NRV2D_8 : M_NRV2B_8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -68,16 +67,125 @@ const int *PackExe::getFilters() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int PackExe::fillExeHeader(struct exe_header_t *eh) const
|
||||||
|
{
|
||||||
|
#define oh (*eh)
|
||||||
|
// fill new exe header
|
||||||
|
int flag = 0;
|
||||||
|
if (!opt->dos.no_reloc)
|
||||||
|
flag |= USEJUMP;
|
||||||
|
if (ih.relocs == 0)
|
||||||
|
flag |= NORELOC;
|
||||||
|
|
||||||
|
memset(&oh,0,sizeof(oh));
|
||||||
|
oh.ident = 'M' + 'Z' * 256;
|
||||||
|
oh.headsize16 = 2;
|
||||||
|
oh.ip = 0;
|
||||||
|
|
||||||
|
oh.sp = ih.sp > 0x200 ? ih.sp : 0x200;
|
||||||
|
|
||||||
|
unsigned destpara = (ph.u_len + ph.overlap_overhead - ph.c_len + 31) / 16;
|
||||||
|
oh.ss = ph.c_len/16 + destpara;
|
||||||
|
if (ih.ss*16 + ih.sp < 0x100000 && ih.ss > oh.ss && ih.sp > 0x200)
|
||||||
|
oh.ss = ih.ss;
|
||||||
|
if (oh.ss*16 + 0x50 < ih.ss*16 + ih.sp
|
||||||
|
&& oh.ss*16 + 0x200 > ih.ss*16 + ih.sp)
|
||||||
|
oh.ss += 0x20;
|
||||||
|
|
||||||
|
if (oh.ss != ih.ss)
|
||||||
|
flag |= SS;
|
||||||
|
if (oh.sp != ih.sp)
|
||||||
|
flag |= SP;
|
||||||
|
return flag;
|
||||||
|
#undef oh
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int PackExe::buildLoader(const Filter *)
|
||||||
|
{
|
||||||
|
struct exe_header_t tmp_oh;
|
||||||
|
int flag = fillExeHeader(&tmp_oh);
|
||||||
|
|
||||||
|
// prepare loader
|
||||||
|
initLoader(nrv_loader,sizeof(nrv_loader));
|
||||||
|
addLoader("EXEENTRY",
|
||||||
|
relocsize ? "EXERELPU" : "",
|
||||||
|
"EXEMAIN4""+G5DXXXX""UPX1HEAD""EXECUTPO",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
if (ph.method == M_NRV2B_8)
|
||||||
|
addLoader("NRV2B16S", // decompressor
|
||||||
|
ph.u_len > DI_LIMIT ? "N2B64K01" : "",
|
||||||
|
"NRV2BEX1",
|
||||||
|
opt->cpu == opt->CPU_8086 ? "N2BX8601" : "N2B28601",
|
||||||
|
"NRV2BEX2",
|
||||||
|
opt->cpu == opt->CPU_8086 ? "N2BX8602" : "N2B28602",
|
||||||
|
"NRV2BEX3",
|
||||||
|
ph.c_len > 0xffff ? "N2B64K02" : "",
|
||||||
|
"NRV2BEX9""NRV2B16E",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
else if (ph.method == M_NRV2D_8)
|
||||||
|
addLoader("NRV2D16S",
|
||||||
|
ph.u_len > DI_LIMIT ? "N2D64K01" : "",
|
||||||
|
"NRV2DEX1",
|
||||||
|
opt->cpu == opt->CPU_8086 ? "N2DX8601" : "N2D28601",
|
||||||
|
"NRV2DEX2",
|
||||||
|
opt->cpu == opt->CPU_8086 ? "N2DX8602" : "N2D28602",
|
||||||
|
"NRV2DEX3",
|
||||||
|
ph.c_len > 0xffff ? "N2D64K02" : "",
|
||||||
|
"NRV2DEX9""NRV2D16E",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
else if (ph.method == M_NRV2E_8)
|
||||||
|
addLoader("NRV2E16S",
|
||||||
|
ph.u_len > DI_LIMIT ? "N2E64K01" : "",
|
||||||
|
"NRV2EEX1",
|
||||||
|
opt->cpu == opt->CPU_8086 ? "N2EX8601" : "N2E28601",
|
||||||
|
"NRV2EEX2",
|
||||||
|
opt->cpu == opt->CPU_8086 ? "N2EX8602" : "N2E28602",
|
||||||
|
"NRV2EEX3",
|
||||||
|
ph.c_len > 0xffff ? "N2E64K02" : "",
|
||||||
|
"NRV2EEX9""NRV2E16E",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
else
|
||||||
|
throwInternalError("unknown compression method");
|
||||||
|
addLoader("EXEMAIN5", NULL);
|
||||||
|
if (relocsize)
|
||||||
|
addLoader(ph.u_len <= DI_LIMIT || (ph.u_len & 0x7fff) >= relocsize ? "EXENOADJ" : "EXEADJUS",
|
||||||
|
"EXERELO1",
|
||||||
|
has_9a ? "EXEREL9A" : "",
|
||||||
|
"EXERELO2",
|
||||||
|
ih_exesize > 0xFE00 ? "EXEREBIG" : "",
|
||||||
|
"EXERELO3",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
addLoader("EXEMAIN8",
|
||||||
|
(flag & SS) ? "EXESTACK" : "",
|
||||||
|
(flag & SP) ? "EXESTASP" : "",
|
||||||
|
(flag & USEJUMP) ? "EXEJUMPF" : "",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
if (!(flag & USEJUMP))
|
||||||
|
addLoader(ih.cs ? "EXERCSPO" : "",
|
||||||
|
"EXERETIP",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
return getLoaderSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
bool PackExe::readFileHeader()
|
int PackExe::readFileHeader()
|
||||||
{
|
{
|
||||||
ih_exesize = ih_imagesize = ih_overlay = 0;
|
ih_exesize = ih_imagesize = ih_overlay = 0;
|
||||||
fi->readx(&ih,sizeof(ih));
|
fi->readx(&ih,sizeof(ih));
|
||||||
if (ih.ident != 'M' + 'Z'*256 && ih.ident != 'Z' + 'M'*256)
|
if (ih.ident != 'M' + 'Z'*256 && ih.ident != 'Z' + 'M'*256)
|
||||||
return false;
|
return 0;
|
||||||
ih_exesize = ih.m512 + ih.p512*512 - (ih.m512 ? 512 : 0);
|
ih_exesize = ih.m512 + ih.p512*512 - (ih.m512 ? 512 : 0);
|
||||||
ih_imagesize = ih_exesize - ih.headsize16*16;
|
ih_imagesize = ih_exesize - ih.headsize16*16;
|
||||||
ih_overlay = file_size - ih_exesize;
|
ih_overlay = file_size - ih_exesize;
|
||||||
@@ -88,7 +196,7 @@ bool PackExe::readFileHeader()
|
|||||||
#if 0
|
#if 0
|
||||||
printf("dos/exe header: %d %d %d\n", ih_exesize, ih_imagesize, ih_overlay);
|
printf("dos/exe header: %d %d %d\n", ih_exesize, ih_imagesize, ih_overlay);
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return UPX_F_DOS_EXE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -123,7 +231,7 @@ unsigned optimize_relocs(upx_byte *b, const unsigned size,
|
|||||||
const upx_byte *relocs, const unsigned nrelocs,
|
const upx_byte *relocs, const unsigned nrelocs,
|
||||||
upx_byte *crel, bool *has_9a)
|
upx_byte *crel, bool *has_9a)
|
||||||
{
|
{
|
||||||
upx_byte *crel_save = crel;
|
upx_byte * const crel_save = crel;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
unsigned seg_high = 0;
|
unsigned seg_high = 0;
|
||||||
#if 0
|
#if 0
|
||||||
@@ -241,35 +349,25 @@ unsigned optimize_relocs(upx_byte *b, const unsigned size,
|
|||||||
void PackExe::pack(OutputFile *fo)
|
void PackExe::pack(OutputFile *fo)
|
||||||
{
|
{
|
||||||
unsigned ic;
|
unsigned ic;
|
||||||
unsigned char flag = 0;
|
|
||||||
|
|
||||||
unsigned char extra_info[32];
|
|
||||||
unsigned eisize = 0;
|
|
||||||
|
|
||||||
//
|
|
||||||
const unsigned exesize = ih_exesize;
|
|
||||||
const unsigned imagesize = ih_imagesize;
|
|
||||||
const unsigned overlay = ih_overlay;
|
|
||||||
if (ih.relocs > MAXRELOCS)
|
if (ih.relocs > MAXRELOCS)
|
||||||
throwCantPack("too many relocations");
|
throwCantPack("too many relocations");
|
||||||
checkOverlay(overlay);
|
checkOverlay(ih_overlay);
|
||||||
|
|
||||||
// alloc buffers
|
// alloc buffers
|
||||||
unsigned relocsize = RSFCRI + 4*ih.relocs;
|
relocsize = RSFCRI + 4*ih.relocs;
|
||||||
|
ibuf.alloc(ih_imagesize+16+relocsize+2);
|
||||||
ibuf.alloc(imagesize+16+relocsize+2);
|
obuf.allocForCompression(ih_imagesize+16+relocsize+2);
|
||||||
obuf.allocForCompression(imagesize+16+relocsize+2);
|
|
||||||
|
|
||||||
// read image
|
// read image
|
||||||
fi->seek(ih.headsize16*16,SEEK_SET);
|
fi->seek(ih.headsize16*16,SEEK_SET);
|
||||||
fi->readx(ibuf,imagesize);
|
fi->readx(ibuf,ih_imagesize);
|
||||||
|
|
||||||
if (find_le32(ibuf, UPX_MIN(imagesize, 127u), UPX_MAGIC_LE32) >= 0)
|
checkAlreadyPacked(ibuf, UPX_MIN(ih_imagesize, 127u));
|
||||||
throwAlreadyPacked();
|
|
||||||
|
|
||||||
// relocations
|
// relocations
|
||||||
has_9a = false;
|
has_9a = false;
|
||||||
upx_byte *w = ibuf + imagesize;
|
upx_byte *w = ibuf + ih_imagesize;
|
||||||
if (ih.relocs)
|
if (ih.relocs)
|
||||||
{
|
{
|
||||||
upx_byte *wr = w + RSFCRI;
|
upx_byte *wr = w + RSFCRI;
|
||||||
@@ -283,7 +381,7 @@ void PackExe::pack(OutputFile *fo)
|
|||||||
set_le32(wr+4*ic, (jc>>16)*16+(jc&0xffff));
|
set_le32(wr+4*ic, (jc>>16)*16+(jc&0xffff));
|
||||||
}
|
}
|
||||||
qsort(wr,ih.relocs,4,le32_compare);
|
qsort(wr,ih.relocs,4,le32_compare);
|
||||||
relocsize = optimize_relocs(ibuf, imagesize, wr, ih.relocs, w, &has_9a);
|
relocsize = optimize_relocs(ibuf, ih_imagesize, wr, ih.relocs, w, &has_9a);
|
||||||
set_le16(w+relocsize, relocsize+2);
|
set_le16(w+relocsize, relocsize+2);
|
||||||
relocsize += 2;
|
relocsize += 2;
|
||||||
if (relocsize > MAXRELOCS)
|
if (relocsize > MAXRELOCS)
|
||||||
@@ -298,121 +396,38 @@ void PackExe::pack(OutputFile *fo)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
flag |= NORELOC;
|
|
||||||
relocsize = 0;
|
relocsize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ph.u_len = imagesize + relocsize;
|
// prepare packheader
|
||||||
if (!compress(ibuf,obuf,0,MAXMATCH))
|
ph.u_len = ih_imagesize + relocsize;
|
||||||
throwNotCompressible();
|
// prepare filter
|
||||||
const unsigned overlapoh = findOverlapOverhead(obuf,32);
|
Filter ft(ph.level);
|
||||||
|
// compress
|
||||||
|
compressWithFilters(&ft, 32, 0, NULL, 0, MAXMATCH);
|
||||||
if (ph.max_run_found + ph.max_match_found > 0x8000)
|
if (ph.max_run_found + ph.max_match_found > 0x8000)
|
||||||
throwCantPack("decompressor limit exceeded, send a bugreport");
|
throwCantPack("decompressor limit exceeded, send a bugreport");
|
||||||
|
|
||||||
#ifdef TESTING
|
#ifdef TESTING
|
||||||
if (opt->debug)
|
if (opt->debug)
|
||||||
{
|
{
|
||||||
printf("image+relocs %d -> %d\n",imagesize+relocsize,ph.c_len);
|
printf("image+relocs %d -> %d\n",ih_imagesize+relocsize,ph.c_len);
|
||||||
printf("offsets: %d - %d\nmatches: %d - %d\nruns: %d - %d\n",
|
printf("offsets: %d - %d\nmatches: %d - %d\nruns: %d - %d\n",
|
||||||
0/*ph.min_offset_found*/,ph.max_offset_found,
|
0/*ph.min_offset_found*/,ph.max_offset_found,
|
||||||
0/*ph.min_match_found*/,ph.max_match_found,
|
0/*ph.min_match_found*/,ph.max_match_found,
|
||||||
0/*ph.min_run_found*/,ph.max_run_found);
|
0/*ph.min_run_found*/,ph.max_run_found);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
const unsigned packedsize = ph.c_len;
|
|
||||||
|
|
||||||
if (!opt->dos.no_reloc)
|
int flag = fillExeHeader(&oh);
|
||||||
flag |= USEJUMP;
|
|
||||||
|
|
||||||
// fill new exe header
|
|
||||||
memset(&oh,0,sizeof(oh));
|
|
||||||
oh.ident = 'M' + 'Z' * 256;
|
|
||||||
|
|
||||||
unsigned destpara = (ph.u_len+overlapoh-packedsize+31)/16;
|
|
||||||
|
|
||||||
oh.ss = packedsize/16 + destpara;
|
|
||||||
if (ih.ss*16 + ih.sp < 0x100000 && ih.ss > oh.ss && ih.sp > 0x200)
|
|
||||||
oh.ss = ih.ss;
|
|
||||||
oh.sp = ih.sp > 0x200 ? ih.sp : 0x200;
|
|
||||||
if (oh.ss*16u + 0x50 < ih.ss*16u + ih.sp
|
|
||||||
&& oh.ss*16u + 0x200 > ih.ss*16u + ih.sp)
|
|
||||||
oh.ss += 0x20;
|
|
||||||
|
|
||||||
destpara = oh.ss - packedsize/16;
|
|
||||||
if (oh.ss != ih.ss)
|
|
||||||
{
|
|
||||||
set_le16(extra_info+eisize,ih.ss);
|
|
||||||
eisize += 2;
|
|
||||||
flag |= SS;
|
|
||||||
}
|
|
||||||
if (oh.sp != ih.sp)
|
|
||||||
{
|
|
||||||
set_le16(extra_info+eisize,ih.sp);
|
|
||||||
eisize += 2;
|
|
||||||
flag |= SP;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DI_LIMIT 0xff00 // see the assembly why
|
|
||||||
// prepare loader
|
|
||||||
initLoader(nrv_loader,sizeof(nrv_loader));
|
|
||||||
addLoader("EXEENTRY",
|
|
||||||
relocsize ? "EXERELPU" : "",
|
|
||||||
"EXEMAIN4""+G5DXXXX""UPX1HEAD""EXECUTPO",
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
if (ph.method == M_NRV2B_8)
|
|
||||||
addLoader("NRV2B16S", // decompressor
|
|
||||||
ph.u_len > DI_LIMIT ? "NDIGT64K" : "",
|
|
||||||
"NRV2BEX1",
|
|
||||||
opt->cpu == opt->CPU_8086 ? "N2BX8601" : "N2B28601",
|
|
||||||
"NRV2BEX2",
|
|
||||||
opt->cpu == opt->CPU_8086 ? "N2BX8602" : "N2B28602",
|
|
||||||
"NRV2BEX3",
|
|
||||||
packedsize > 0xffff ? "NSIGT64K" : "",
|
|
||||||
"NRV2BEX9""NRV2B16E",
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
else if (ph.method == M_NRV2D_8)
|
|
||||||
addLoader("NRV2D16S",
|
|
||||||
ph.u_len > DI_LIMIT ? "NDIGT64D" : "",
|
|
||||||
"NRV2DEX1",
|
|
||||||
opt->cpu == opt->CPU_8086 ? "N2DX8601" : "N2D28601",
|
|
||||||
"NRV2DEX2",
|
|
||||||
opt->cpu == opt->CPU_8086 ? "N2DX8602" : "N2D28602",
|
|
||||||
"NRV2DEX3",
|
|
||||||
packedsize > 0xffff ? "NSIGT64D" : "",
|
|
||||||
"NRV2DEX9""NRV2D16E",
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
else
|
|
||||||
throwInternalError("unknown compression method");
|
|
||||||
addLoader("EXEMAIN5", NULL);
|
|
||||||
if (relocsize)
|
|
||||||
addLoader(ph.u_len <= DI_LIMIT || (ph.u_len & 0x7fff) >= relocsize ? "EXENOADJ" : "EXEADJUS",
|
|
||||||
"EXERELO1",
|
|
||||||
has_9a ? "EXEREL9A" : "",
|
|
||||||
"EXERELO2",
|
|
||||||
exesize > 0xFE00 ? "EXEREBIG" : "",
|
|
||||||
"EXERELO3",
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
addLoader("EXEMAIN8",
|
|
||||||
(flag & SS) ? "EXESTACK" : "",
|
|
||||||
(flag & SP) ? "EXESTASP" : "",
|
|
||||||
(flag & USEJUMP) ? "EXEJUMPF" : "",
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
if (!(flag & USEJUMP))
|
|
||||||
addLoader(ih.cs ? "EXERCSPO" : "",
|
|
||||||
"EXERETIP",
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
const unsigned lsize = getLoaderSize();
|
const unsigned lsize = getLoaderSize();
|
||||||
MemBuffer loader(lsize);
|
MemBuffer loader(lsize);
|
||||||
memcpy(loader,getLoader(),lsize);
|
memcpy(loader,getLoader(),lsize);
|
||||||
//OutputFile::dump("xxloader.dat", loader, lsize);
|
//OutputFile::dump("xxloader.dat", loader, lsize);
|
||||||
|
|
||||||
// patch loader
|
// patch loader
|
||||||
|
const unsigned packedsize = ph.c_len;
|
||||||
const unsigned e_len = getLoaderSectionStart("EXECUTPO");
|
const unsigned e_len = getLoaderSectionStart("EXECUTPO");
|
||||||
const unsigned d_len = lsize - e_len;
|
const unsigned d_len = lsize - e_len;
|
||||||
assert((e_len&15) == 0);
|
assert((e_len&15) == 0);
|
||||||
@@ -420,17 +435,29 @@ void PackExe::pack(OutputFile *fo)
|
|||||||
const unsigned copysize = (1+packedsize+d_len) & ~1;
|
const unsigned copysize = (1+packedsize+d_len) & ~1;
|
||||||
const unsigned firstcopy = copysize%0x10000 ? copysize%0x10000 : 0x10000;
|
const unsigned firstcopy = copysize%0x10000 ? copysize%0x10000 : 0x10000;
|
||||||
|
|
||||||
oh.headsize16 = 2;
|
// set oh.min & oh.max
|
||||||
oh.ip = 0;
|
ic = ih.min*16 + ih_imagesize;
|
||||||
|
if (ic < oh.ss*16 + oh.sp)
|
||||||
ic = ih.min*16+imagesize;
|
ic = oh.ss*16 + oh.sp;
|
||||||
if (ic < oh.ss*16u + oh.sp)
|
|
||||||
ic = oh.ss*16u + oh.sp;
|
|
||||||
|
|
||||||
oh.min = (ic - (packedsize + lsize)) / 16;
|
oh.min = (ic - (packedsize + lsize)) / 16;
|
||||||
ic = ((unsigned) oh.min) + (ih.max - ih.min);
|
ic = oh.min + (ih.max - ih.min);
|
||||||
oh.max = ic < 0xffff && ih.max != 0xffff ? ic : 0xffff;
|
oh.max = ic < 0xffff && ih.max != 0xffff ? ic : 0xffff;
|
||||||
|
|
||||||
|
// set extra info
|
||||||
|
unsigned char extra_info[9];
|
||||||
|
unsigned eisize = 0;
|
||||||
|
if (oh.ss != ih.ss)
|
||||||
|
{
|
||||||
|
set_le16(extra_info+eisize,ih.ss);
|
||||||
|
eisize += 2;
|
||||||
|
assert((flag & SS) != 0); // set in fillExeHeader()
|
||||||
|
}
|
||||||
|
if (oh.sp != ih.sp)
|
||||||
|
{
|
||||||
|
set_le16(extra_info+eisize,ih.sp);
|
||||||
|
eisize += 2;
|
||||||
|
assert((flag & SP) != 0); // set in fillExeHeader()
|
||||||
|
}
|
||||||
if (ih.min != oh.min)
|
if (ih.min != oh.min)
|
||||||
{
|
{
|
||||||
set_le16(extra_info+eisize,ih.min);
|
set_le16(extra_info+eisize,ih.min);
|
||||||
@@ -443,7 +470,9 @@ void PackExe::pack(OutputFile *fo)
|
|||||||
eisize += 2;
|
eisize += 2;
|
||||||
flag |= MAXMEM;
|
flag |= MAXMEM;
|
||||||
}
|
}
|
||||||
|
extra_info[eisize++] = (unsigned char) flag;
|
||||||
|
|
||||||
|
// patch loader
|
||||||
if (flag & USEJUMP)
|
if (flag & USEJUMP)
|
||||||
{
|
{
|
||||||
// I use a relocation entry to set the original cs
|
// I use a relocation entry to set the original cs
|
||||||
@@ -461,7 +490,10 @@ void PackExe::pack(OutputFile *fo)
|
|||||||
oh.relocs = 0;
|
oh.relocs = 0;
|
||||||
oh.firstreloc = ih.cs*0x10000 + ih.ip;
|
oh.firstreloc = ih.cs*0x10000 + ih.ip;
|
||||||
}
|
}
|
||||||
oh.relocoffs = offsetof(exe_header_t, firstreloc);
|
|
||||||
|
// g++ 3.1 does not like the following line...
|
||||||
|
// oh.relocoffs = offsetof(exe_header_t, firstreloc);
|
||||||
|
oh.relocoffs = ptr_diff(&oh.firstreloc, &oh);
|
||||||
|
|
||||||
if (flag & SP)
|
if (flag & SP)
|
||||||
patch_le16(loader,lsize,"SP",ih.sp);
|
patch_le16(loader,lsize,"SP",ih.sp);
|
||||||
@@ -475,6 +507,7 @@ void PackExe::pack(OutputFile *fo)
|
|||||||
patch_le16(loader,e_len,"BX",0x800F + 0x10*((packedsize&15)+1) - 0x10);
|
patch_le16(loader,e_len,"BX",0x800F + 0x10*((packedsize&15)+1) - 0x10);
|
||||||
patch_le16(loader,e_len,"BP",(packedsize&15)+1);
|
patch_le16(loader,e_len,"BP",(packedsize&15)+1);
|
||||||
|
|
||||||
|
unsigned destpara = oh.ss - ph.c_len/16;
|
||||||
patch_le16(loader,e_len,"ES",destpara-e_len/16);
|
patch_le16(loader,e_len,"ES",destpara-e_len/16);
|
||||||
patch_le16(loader,e_len,"DS",e_len/16+(copysize-firstcopy)/16);
|
patch_le16(loader,e_len,"DS",e_len/16+(copysize-firstcopy)/16);
|
||||||
patch_le16(loader,e_len,"SI",firstcopy-2);
|
patch_le16(loader,e_len,"SI",firstcopy-2);
|
||||||
@@ -484,12 +517,11 @@ void PackExe::pack(OutputFile *fo)
|
|||||||
//if (ih.relocoffs >= 0x40 && memcmp(&ih.relocoffs,">TIPPACH",8))
|
//if (ih.relocoffs >= 0x40 && memcmp(&ih.relocoffs,">TIPPACH",8))
|
||||||
// throwCantPack("FIXME");
|
// throwCantPack("FIXME");
|
||||||
|
|
||||||
extra_info[eisize++] = flag;
|
|
||||||
const unsigned outputlen = sizeof(oh)+lsize+packedsize+eisize;
|
const unsigned outputlen = sizeof(oh)+lsize+packedsize+eisize;
|
||||||
oh.m512 = outputlen & 511;
|
oh.m512 = outputlen & 511;
|
||||||
oh.p512 = (outputlen + 511) >> 9;
|
oh.p512 = (outputlen + 511) >> 9;
|
||||||
|
|
||||||
//fprintf(stderr,"\ne_len=%x d_len=%x clen=%x oo=%x ulen=%x destp=%x copys=%x images=%x",e_len,d_len,packedsize,overlapoh,ph.u_len,destpara,copysize,imagesize);
|
//fprintf(stderr,"\ne_len=%x d_len=%x clen=%x oo=%x ulen=%x destp=%x copys=%x images=%x",e_len,d_len,packedsize,ph.overlap_overhead,ph.u_len,destpara,copysize,ih_imagesize);
|
||||||
|
|
||||||
// write header + write loader + compressed file
|
// write header + write loader + compressed file
|
||||||
#ifdef TESTING
|
#ifdef TESTING
|
||||||
@@ -511,10 +543,10 @@ void PackExe::pack(OutputFile *fo)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
verifyOverlappingDecompression(&obuf, overlapoh);
|
verifyOverlappingDecompression();
|
||||||
|
|
||||||
// copy the overlay
|
// copy the overlay
|
||||||
copyOverlay(fo, overlay, &obuf);
|
copyOverlay(fo, ih_overlay, &obuf);
|
||||||
//fprintf (stderr,"%x %x\n",relocsize,ph.u_len);
|
//fprintf (stderr,"%x %x\n",relocsize,ph.u_len);
|
||||||
|
|
||||||
// finally check the compression ratio
|
// finally check the compression ratio
|
||||||
@@ -548,23 +580,22 @@ void PackExe::unpack(OutputFile *fo)
|
|||||||
obuf.allocForUncompression(ph.u_len);
|
obuf.allocForUncompression(ph.u_len);
|
||||||
|
|
||||||
// read the file
|
// read the file
|
||||||
unsigned imagesize = ih_imagesize;
|
|
||||||
const unsigned overlay = ih_overlay;
|
|
||||||
|
|
||||||
fi->seek(ih.headsize16*16,SEEK_SET);
|
fi->seek(ih.headsize16*16,SEEK_SET);
|
||||||
fi->readx(ibuf,imagesize);
|
fi->readx(ibuf,ih_imagesize);
|
||||||
|
|
||||||
// get compressed data offset
|
// get compressed data offset
|
||||||
unsigned e_len = ph.buf_offset + ph.getPackHeaderSize();
|
unsigned e_len = ph.buf_offset + ph.getPackHeaderSize();
|
||||||
if (imagesize <= e_len + ph.c_len)
|
if (ih_imagesize <= e_len + ph.c_len)
|
||||||
throwCantUnpack("file damaged");
|
throwCantUnpack("file damaged");
|
||||||
|
|
||||||
checkOverlay(overlay);
|
checkOverlay(ih_overlay);
|
||||||
|
|
||||||
// decompress
|
// decompress
|
||||||
decompress(ibuf+e_len,obuf);
|
decompress(ibuf+e_len,obuf);
|
||||||
|
|
||||||
const unsigned char flag = ibuf[imagesize-1];
|
unsigned imagesize = ih_imagesize;
|
||||||
|
imagesize--;
|
||||||
|
const unsigned char flag = ibuf[imagesize];
|
||||||
|
|
||||||
unsigned relocn = 0;
|
unsigned relocn = 0;
|
||||||
upx_byte *relocs = obuf + ph.u_len;
|
upx_byte *relocs = obuf + ph.u_len;
|
||||||
@@ -614,20 +645,23 @@ void PackExe::unpack(OutputFile *fo)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fill new exe header
|
// fill new exe header
|
||||||
memset(&oh,0,sizeof(oh));
|
memset(&oh,0,sizeof(oh));
|
||||||
oh.ident = 'M' + 'Z'*256;
|
oh.ident = 'M' + 'Z'*256;
|
||||||
|
|
||||||
|
if (relocn)
|
||||||
|
{
|
||||||
oh.relocs = relocn;
|
oh.relocs = relocn;
|
||||||
while (relocn & 3)
|
while (relocn & 3)
|
||||||
set_le32(wrkmem+4*relocn++,0);
|
set_le32(wrkmem+4*relocn++,0);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned outputlen = sizeof(oh)+relocn*4+relocs-obuf;
|
unsigned outputlen = ptr_diff(relocs, obuf) + sizeof(oh) + relocn*4;
|
||||||
oh.m512 = outputlen & 511;
|
oh.m512 = outputlen & 511;
|
||||||
oh.p512 = (outputlen + 511) >> 9;
|
oh.p512 = (outputlen + 511) >> 9;
|
||||||
oh.headsize16 = 2+relocn/4;
|
oh.headsize16 = 2+relocn/4;
|
||||||
|
|
||||||
imagesize--;
|
|
||||||
oh.max = ih.max;
|
oh.max = ih.max;
|
||||||
oh.min = ih.min;
|
oh.min = ih.min;
|
||||||
oh.sp = ih.sp;
|
oh.sp = ih.sp;
|
||||||
@@ -653,11 +687,12 @@ void PackExe::unpack(OutputFile *fo)
|
|||||||
|
|
||||||
// write header + relocations + uncompressed file
|
// write header + relocations + uncompressed file
|
||||||
fo->write(&oh,sizeof(oh));
|
fo->write(&oh,sizeof(oh));
|
||||||
|
if (relocn)
|
||||||
fo->write(wrkmem,relocn*4);
|
fo->write(wrkmem,relocn*4);
|
||||||
fo->write(obuf,relocs-obuf);
|
fo->write(obuf, ptr_diff(relocs, obuf));
|
||||||
|
|
||||||
// copy the overlay
|
// copy the overlay
|
||||||
copyOverlay(fo, overlay, &obuf);
|
copyOverlay(fo, ih_overlay, &obuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+16
-7
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -39,10 +39,10 @@ class PackExe : public Packer
|
|||||||
typedef Packer super;
|
typedef Packer super;
|
||||||
public:
|
public:
|
||||||
PackExe(InputFile *f);
|
PackExe(InputFile *f);
|
||||||
virtual int getVersion() const { return 11; }
|
virtual int getVersion() const { return 13; }
|
||||||
virtual int getFormat() const { return UPX_F_DOS_EXE; }
|
virtual int getFormat() const { return UPX_F_DOS_EXE; }
|
||||||
virtual const char *getName() const { return "dos/exe"; }
|
virtual const char *getName() const { return "dos/exe"; }
|
||||||
virtual int getCompressionMethod() const;
|
virtual const int *getCompressionMethods(int method, int level) const;
|
||||||
virtual const int *getFilters() const;
|
virtual const int *getFilters() const;
|
||||||
|
|
||||||
virtual void pack(OutputFile *fo);
|
virtual void pack(OutputFile *fo);
|
||||||
@@ -63,7 +63,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool readFileHeader(void);
|
struct exe_header_t;
|
||||||
|
|
||||||
|
virtual int readFileHeader(void);
|
||||||
|
|
||||||
|
virtual int fillExeHeader(struct exe_header_t *) const;
|
||||||
|
virtual int buildLoader(const Filter *ft);
|
||||||
|
|
||||||
struct exe_header_t
|
struct exe_header_t
|
||||||
{
|
{
|
||||||
@@ -82,11 +87,15 @@ protected:
|
|||||||
LE16 relocoffs;
|
LE16 relocoffs;
|
||||||
char __[2]; // overlnum
|
char __[2]; // overlnum
|
||||||
LE32 firstreloc;
|
LE32 firstreloc;
|
||||||
} ih, oh;
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
|
exe_header_t ih, oh;
|
||||||
|
|
||||||
unsigned ih_exesize;
|
unsigned ih_exesize;
|
||||||
unsigned ih_imagesize;
|
unsigned ih_imagesize;
|
||||||
unsigned ih_overlay;
|
unsigned ih_overlay;
|
||||||
|
unsigned relocsize;
|
||||||
|
|
||||||
bool has_9a;
|
bool has_9a;
|
||||||
|
|
||||||
|
|||||||
+251
-238
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
Copyright (C) 2000 John F. Reiser
|
Copyright (C) 2000-2002 John F. Reiser
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,275 +22,251 @@
|
|||||||
If not, write to the Free Software Foundation, Inc.,
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar John F. Reiser
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu jreiser@BitWagon.com
|
||||||
|
|
||||||
John F. Reiser
|
|
||||||
jreiser@BitWagon.com
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
#include "filter.h"
|
||||||
|
#include "linker.h"
|
||||||
#include "packer.h"
|
#include "packer.h"
|
||||||
#include "p_elf.h"
|
#include "p_elf.h"
|
||||||
#include "p_unix.h"
|
#include "p_unix.h"
|
||||||
|
#include "p_lx_exc.h"
|
||||||
#include "p_lx_elf.h"
|
#include "p_lx_elf.h"
|
||||||
|
|
||||||
|
#define PT_LOAD Elf_LE32_Phdr::PT_LOAD
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
static const
|
static const
|
||||||
#include "stub/l_le_n2b.h"
|
#include "stub/l_lx_elf86.h"
|
||||||
static const
|
static const
|
||||||
#include "stub/l_le_n2d.h"
|
#include "stub/fold_elf86.h"
|
||||||
|
|
||||||
|
|
||||||
|
PackLinuxI386elf::PackLinuxI386elf(InputFile *f) :
|
||||||
|
super(f), phdri(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
PackLinuxI386elf::~PackLinuxI386elf()
|
PackLinuxI386elf::~PackLinuxI386elf()
|
||||||
{
|
{
|
||||||
delete phdri;
|
delete[] phdri;
|
||||||
}
|
}
|
||||||
|
|
||||||
PackLinuxI386elf::PackLinuxI386elf(InputFile *f)
|
int const *
|
||||||
:super(f)
|
PackLinuxI386elf::getFilters() const
|
||||||
,phdri(0)
|
|
||||||
{
|
{
|
||||||
|
static const int filters[] = {
|
||||||
|
0x49, 0x46,
|
||||||
|
#if 1
|
||||||
|
0x26, 0x24, 0x11, 0x14, 0x13, 0x16, 0x25, 0x15, 0x12,
|
||||||
|
#else
|
||||||
|
0x83, 0x36, 0x26,
|
||||||
|
0x86, 0x80,
|
||||||
|
0x84, 0x87, 0x81,
|
||||||
|
0x82, 0x85,
|
||||||
|
0x24, 0x16, 0x13, 0x14, 0x11, 0x25, 0x15, 0x12,
|
||||||
|
#endif
|
||||||
|
-1 };
|
||||||
|
return filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
const upx_byte *PackLinuxI386elf::getLoader() const
|
int
|
||||||
|
PackLinuxI386elf::buildLoader(const Filter *ft)
|
||||||
{
|
{
|
||||||
if (M_IS_NRV2B(opt->method))
|
unsigned char tmp[sizeof(linux_i386elf_fold)];
|
||||||
return linux_i386elf_nrv2b_loader;
|
memcpy(tmp, linux_i386elf_fold, sizeof(linux_i386elf_fold));
|
||||||
if (M_IS_NRV2D(opt->method))
|
checkPatch(NULL, 0, 0, 0); // reset
|
||||||
return linux_i386elf_nrv2d_loader;
|
if (opt->unix.ptinterp) {
|
||||||
return NULL;
|
unsigned j;
|
||||||
|
for (j = 0; j < sizeof(linux_i386elf_fold)-1; ++j) {
|
||||||
|
if (0x60==tmp[ j]
|
||||||
|
&& 0x47==tmp[1+j] ) {
|
||||||
|
/* put INC EDI before PUSHA: inhibits auxv_up for PT_INTERP */
|
||||||
|
tmp[ j] = 0x47;
|
||||||
|
tmp[1+j] = 0x60;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PackLinuxI386elf::getLoaderSize() const
|
|
||||||
{
|
|
||||||
if (0 != lsize) {
|
|
||||||
return lsize;
|
|
||||||
}
|
}
|
||||||
if (M_IS_NRV2B(opt->method))
|
}
|
||||||
return sizeof(linux_i386elf_nrv2b_loader);
|
return buildLinuxLoader(
|
||||||
if (M_IS_NRV2D(opt->method))
|
linux_i386elf_loader, sizeof(linux_i386elf_loader),
|
||||||
return sizeof(linux_i386elf_nrv2d_loader);
|
tmp, sizeof(linux_i386elf_fold), ft );
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline off_t min_off_t(off_t a, off_t b)
|
void PackLinuxI386elf::patchLoader() { }
|
||||||
{
|
|
||||||
return a < b ? a : b;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline off_t max_off_t(off_t a, off_t b)
|
|
||||||
{
|
|
||||||
return a > b ? a : b;
|
|
||||||
}
|
|
||||||
|
|
||||||
static off_t getbrk(Elf_LE32_Phdr const *phdr, int e_phnum)
|
|
||||||
{
|
|
||||||
off_t brka = 0;
|
|
||||||
for (int j = 0; j < e_phnum; ++phdr, ++j) if (PT_LOAD==phdr->p_type) {
|
|
||||||
brka = max_off_t(brka, phdr->p_vaddr + phdr->p_memsz);
|
|
||||||
}
|
|
||||||
return brka;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PackLinuxI386elf::updateLoader(OutputFile *fo)
|
|
||||||
{
|
|
||||||
#define PAGE_MASK (~0<<12)
|
|
||||||
Elf_LE32_Phdr *const phdro = (Elf_LE32_Phdr *)(sizeof(Elf_LE32_Ehdr)+loader);
|
|
||||||
off_t const totlen = fo->getBytesWritten();
|
|
||||||
phdro->p_filesz = totlen;
|
|
||||||
|
|
||||||
// pre-calculate for benefit of runtime disappearing act via munmap()
|
|
||||||
phdro->p_memsz = PAGE_MASK & (~PAGE_MASK + totlen);
|
|
||||||
|
|
||||||
patchLoaderChecksum();
|
|
||||||
fo->seek(0, SEEK_SET);
|
|
||||||
fo->rewrite(loader, 0x80);
|
|
||||||
#undef PAGE_MASK
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PackLinuxI386elf::patchLoader()
|
|
||||||
{
|
|
||||||
lsize = getLoaderSize();
|
|
||||||
Elf_LE32_Ehdr *const ehdr = (Elf_LE32_Ehdr *)(void *)loader;
|
|
||||||
Elf_LE32_Phdr *const phdr = (Elf_LE32_Phdr *)(1+ehdr);
|
|
||||||
|
|
||||||
// stub/scripts/setfold.pl puts address of 'fold_begin' in phdr[1].p_offset
|
|
||||||
off_t const fold_begin = phdr[1].p_offset;
|
|
||||||
assert(fold_begin > 0);
|
|
||||||
assert(fold_begin < (off_t)lsize);
|
|
||||||
MemBuffer cprLoader(lsize);
|
|
||||||
|
|
||||||
// compress compiled C-code portion of loader
|
|
||||||
upx_compress_config_t conf; memset(&conf, 0xff, sizeof(conf));
|
|
||||||
conf.c_flags = 0;
|
|
||||||
upx_uint result_buffer[16];
|
|
||||||
upx_uint cprLsize;
|
|
||||||
upx_compress(
|
|
||||||
loader + fold_begin, lsize - fold_begin,
|
|
||||||
cprLoader, &cprLsize,
|
|
||||||
0, // progress_callback_t ??
|
|
||||||
getCompressionMethod(), 9,
|
|
||||||
&conf,
|
|
||||||
result_buffer
|
|
||||||
);
|
|
||||||
set_le32(0+fold_begin+loader, lsize - fold_begin);
|
|
||||||
set_le32(4+fold_begin+loader, cprLsize);
|
|
||||||
memcpy( 8+fold_begin+loader, cprLoader, cprLsize);
|
|
||||||
lsize = 8 + fold_begin + cprLsize;
|
|
||||||
patchVersion(loader,lsize);
|
|
||||||
|
|
||||||
// Info for OS kernel to set the brk()
|
|
||||||
unsigned const brka = getbrk(phdri, ehdri.e_phnum);
|
|
||||||
phdr[1].p_offset = 0xfff&brka;
|
|
||||||
phdr[1].p_vaddr = brka;
|
|
||||||
phdr[1].p_paddr = brka;
|
|
||||||
phdr[1].p_filesz = 0;
|
|
||||||
phdr[1].p_memsz = 0;
|
|
||||||
|
|
||||||
// The beginning of our loader consists of a elf_hdr (52 bytes) and
|
|
||||||
// two sections elf_phdr (2 * 32 byte), so we have 12 free bytes
|
|
||||||
// from offset 116 to the program start at offset 128.
|
|
||||||
assert(ehdr->e_phoff == sizeof(*ehdr));
|
|
||||||
assert(ehdr->e_ehsize == sizeof(*ehdr));
|
|
||||||
assert(ehdr->e_phentsize == sizeof(Elf_LE32_Phdr));
|
|
||||||
assert(ehdr->e_phnum == 2);
|
|
||||||
assert(ehdr->e_shnum == 0);
|
|
||||||
assert(lsize > 128 && lsize < 4096);
|
|
||||||
|
|
||||||
patchLoaderChecksum();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool PackLinuxI386elf::canPack()
|
bool PackLinuxI386elf::canPack()
|
||||||
{
|
{
|
||||||
unsigned char buf[512];
|
unsigned char buf[sizeof(Elf_LE32_Ehdr) + 14*sizeof(Elf_LE32_Phdr)];
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(buf) <= 512);
|
||||||
|
|
||||||
// FIXME: add special checks for uncompresed "vmlinux" kernel
|
exetype = 0;
|
||||||
|
|
||||||
fi->readx(buf,512);
|
fi->readx(buf, sizeof(buf));
|
||||||
fi->seek(0,0);
|
fi->seek(0, SEEK_SET);
|
||||||
if (0==memcmp(buf, "\x7f\x45\x4c\x46\x01\x01\x01", 7)) { // ELF 32-bit LSB
|
|
||||||
Elf_LE32_Ehdr const *const ehdr = (Elf_LE32_Ehdr const *)buf;
|
Elf_LE32_Ehdr const *const ehdr = (Elf_LE32_Ehdr const *)buf;
|
||||||
Elf_LE32_Phdr const *phdr = (Elf_LE32_Phdr const *)(ehdr->e_phoff +
|
|
||||||
(char const *)ehdr);
|
// now check the ELF header
|
||||||
|
if (checkEhdr(ehdr) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// additional requirements for linux/elf386
|
||||||
|
if (ehdr->e_ehsize != sizeof(*ehdr)) {
|
||||||
|
throwCantPack("invalid Ehdr e_ehsize; try `--force-execve'");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (ehdr->e_phoff != sizeof(*ehdr)) {// Phdrs not contiguous with Ehdr
|
if (ehdr->e_phoff != sizeof(*ehdr)) {// Phdrs not contiguous with Ehdr
|
||||||
|
throwCantPack("non-contiguous Ehdr/Phdr; try `--force-execve'");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The first PT_LOAD must cover the beginning of the file (0==p_offset).
|
// The first PT_LOAD must cover the beginning of the file (0==p_offset).
|
||||||
|
Elf_LE32_Phdr const *phdr = (Elf_LE32_Phdr const *)(buf + ehdr->e_phoff);
|
||||||
for (unsigned j=0; j < ehdr->e_phnum; ++phdr, ++j) {
|
for (unsigned j=0; j < ehdr->e_phnum; ++phdr, ++j) {
|
||||||
if (PT_LOAD==phdr->p_type) {
|
if (j >= 14)
|
||||||
|
return false;
|
||||||
|
if (phdr->PT_LOAD == phdr->p_type) {
|
||||||
if (phdr->p_offset != 0) {
|
if (phdr->p_offset != 0) {
|
||||||
|
throwCantPack("invalid Phdr p_offset; try `--force-execve'");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// detect possible conflict upon invocation
|
||||||
|
if (phdr->p_vaddr < (unsigned)(0x400000 + file_size)
|
||||||
|
|| phdr->p_paddr < (unsigned)(0x400000 + file_size) ) {
|
||||||
|
throwAlreadyPackedByUPX(); // not necessarily, but mostly true
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
exetype = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exetype = 1;
|
|
||||||
return super::canPack();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!super::canPack())
|
||||||
|
return false;
|
||||||
|
assert(exetype == 1);
|
||||||
|
|
||||||
|
// set options
|
||||||
|
opt->unix.blocksize = blocksize = file_size;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void PackLinuxI386elf::packExtent(
|
void PackLinuxI386elf::packExtent(
|
||||||
Extent const &x,
|
Extent const &x,
|
||||||
OutputFile *fo,
|
|
||||||
unsigned &total_in,
|
unsigned &total_in,
|
||||||
unsigned &total_out
|
unsigned &total_out,
|
||||||
|
Filter *ft,
|
||||||
|
OutputFile *fo
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
fi->seek(x.offset, SEEK_SET);
|
fi->seek(x.offset, SEEK_SET);
|
||||||
for (off_t rest = x.size; 0!=rest; )
|
for (off_t rest = x.size; 0 != rest; ) {
|
||||||
{
|
int const strategy = getStrategy(*ft);
|
||||||
int l = fi->readx(ibuf, min_off_t(rest, opt->unix.blocksize));
|
int l = fi->readx(ibuf, UPX_MIN(rest, (off_t)blocksize));
|
||||||
if (l == 0)
|
if (l == 0) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
rest -= l;
|
rest -= l;
|
||||||
|
|
||||||
// Note: compression for a block can fail if the
|
// Note: compression for a block can fail if the
|
||||||
// file is e.g. blocksize + 1 bytes long
|
// file is e.g. blocksize + 1 bytes long
|
||||||
|
|
||||||
// compress
|
// compress
|
||||||
ph.u_len = l;
|
ph.c_len = ph.u_len = l;
|
||||||
compress(ibuf, obuf); // ignore return value
|
ph.overlap_overhead = 0;
|
||||||
|
unsigned end_u_adler = 0;
|
||||||
if (ph.c_len < ph.u_len)
|
if (ft) {
|
||||||
{
|
// compressWithFilters() updates u_adler _inside_ compress();
|
||||||
if (!testOverlappingDecompression(obuf, OVERHEAD))
|
// that is, AFTER filtering. We want BEFORE filtering,
|
||||||
throwNotCompressible();
|
// so that decompression checks the end-to-end checksum.
|
||||||
|
end_u_adler = upx_adler32(ibuf, ph.u_len, ph.u_adler);
|
||||||
|
ft->buf_len = l;
|
||||||
|
compressWithFilters(ft, OVERHEAD, strategy);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
(void) compress(ibuf, obuf); // ignore return value
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ph.c_len < ph.u_len) {
|
||||||
|
ph.overlap_overhead = OVERHEAD;
|
||||||
|
if (!testOverlappingDecompression(obuf, ph.overlap_overhead)) {
|
||||||
|
// not in-place compressible
|
||||||
|
ph.c_len = ph.u_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ph.c_len >= ph.u_len) {
|
||||||
|
// block is not compressible
|
||||||
ph.c_len = ph.u_len;
|
ph.c_len = ph.u_len;
|
||||||
// must update checksum of compressed data
|
// must update checksum of compressed data
|
||||||
ph.c_adler = upx_adler32(ph.c_adler, ibuf, ph.u_len);
|
ph.c_adler = upx_adler32(ibuf, ph.u_len, ph.saved_c_adler);
|
||||||
}
|
}
|
||||||
|
|
||||||
// write block sizes
|
// write block sizes
|
||||||
unsigned char size[8];
|
b_info tmp;
|
||||||
set_native32(size+0, ph.u_len);
|
memset(&tmp, 0, sizeof(tmp));
|
||||||
set_native32(size+4, ph.c_len);
|
set_native32(&tmp.sz_unc, ph.u_len);
|
||||||
fo->write(size, 8);
|
set_native32(&tmp.sz_cpr, ph.c_len);
|
||||||
|
if (ph.c_len < ph.u_len) {
|
||||||
|
tmp.b_method = (unsigned char) ph.method;
|
||||||
|
if (ft) {
|
||||||
|
tmp.b_ftid = (unsigned char) ft->id;
|
||||||
|
tmp.b_cto8 = ft->cto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fo->write(&tmp, sizeof(tmp));
|
||||||
|
b_len += sizeof(b_info);
|
||||||
|
|
||||||
// write compressed data
|
// write compressed data
|
||||||
if (ph.c_len < ph.u_len)
|
if (ph.c_len < ph.u_len) {
|
||||||
{
|
|
||||||
fo->write(obuf, ph.c_len);
|
fo->write(obuf, ph.c_len);
|
||||||
verifyOverlappingDecompression(&obuf, OVERHEAD);
|
// Checks ph.u_adler after decompression but before unfiltering
|
||||||
|
verifyOverlappingDecompression();
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
fo->write(ibuf, ph.u_len);
|
fo->write(ibuf, ph.u_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ft) {
|
||||||
|
ph.u_adler = end_u_adler;
|
||||||
|
}
|
||||||
total_in += ph.u_len;
|
total_in += ph.u_len;
|
||||||
total_out += ph.c_len;
|
total_out += ph.c_len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PackLinuxI386elf::pack(OutputFile *fo)
|
void PackLinuxI386elf::pack1(OutputFile *fo, Filter &)
|
||||||
{
|
{
|
||||||
// set options
|
fi->seek(0, SEEK_SET);
|
||||||
opt->unix.blocksize = blocksize = file_size;
|
|
||||||
progid = 0; // not used
|
|
||||||
|
|
||||||
fi->readx(&ehdri, sizeof(ehdri));
|
fi->readx(&ehdri, sizeof(ehdri));
|
||||||
off_t const sz_phdrs = ehdri.e_phnum * ehdri.e_phentsize;
|
assert(ehdri.e_phoff == sizeof(Elf_LE32_Ehdr)); // checked by canPack()
|
||||||
|
sz_phdrs = ehdri.e_phnum * ehdri.e_phentsize;
|
||||||
|
|
||||||
phdri = new Elf_LE32_Phdr[ehdri.e_phnum];
|
phdri = new Elf_LE32_Phdr[ehdri.e_phnum];
|
||||||
fi->seek(ehdri.e_phoff, SEEK_SET);
|
fi->seek(ehdri.e_phoff, SEEK_SET);
|
||||||
fi->readx(phdri, sz_phdrs);
|
fi->readx(phdri, sz_phdrs);
|
||||||
|
|
||||||
// prepare loader
|
generateElfHdr(fo, linux_i386elf_fold, getbrk(phdri, ehdri.e_phnum) );
|
||||||
lsize = getLoaderSize();
|
}
|
||||||
loader.alloc(lsize + sizeof(p_info));
|
|
||||||
memcpy(loader,getLoader(),lsize);
|
|
||||||
|
|
||||||
// patch loader, prepare header info, write loader + header info
|
void PackLinuxI386elf::pack2(OutputFile *fo, Filter &ft)
|
||||||
patchLoader(); // can change lsize by packing upx_main
|
{
|
||||||
p_info *const hbuf = (p_info *)(loader + lsize);
|
|
||||||
set_native32(&hbuf->p_progid, progid);
|
|
||||||
set_native32(&hbuf->p_filesize, file_size);
|
|
||||||
set_native32(&hbuf->p_blocksize, blocksize);
|
|
||||||
fo->write(loader, lsize + sizeof(p_info));
|
|
||||||
|
|
||||||
// init compression buffers
|
|
||||||
ibuf.alloc(blocksize);
|
|
||||||
obuf.allocForCompression(blocksize);
|
|
||||||
|
|
||||||
assert(ehdri.e_phoff == sizeof(Elf_LE32_Ehdr)); // checked by canPack()
|
|
||||||
Extent x;
|
Extent x;
|
||||||
unsigned k;
|
unsigned k;
|
||||||
|
|
||||||
// count passes, set ptload vars
|
// count passes, set ptload vars
|
||||||
ui_total_passes = 0;
|
ui_total_passes = 0;
|
||||||
off_t ptload0hi = 0, ptload1lo = 0;
|
off_t ptload0hi = 0, ptload1lo = 0, ptload1sz = 0;
|
||||||
int nx = 0;
|
|
||||||
for (k = 0; k < ehdri.e_phnum; ++k) {
|
for (k = 0; k < ehdri.e_phnum; ++k) {
|
||||||
if (PT_LOAD == phdri[k].p_type) {
|
if (PT_LOAD == phdri[k].p_type) {
|
||||||
x.offset = phdri[k].p_offset;
|
x.offset = phdri[k].p_offset;
|
||||||
@@ -300,84 +276,78 @@ void PackLinuxI386elf::pack(OutputFile *fo)
|
|||||||
}
|
}
|
||||||
else if (0 == ptload1lo) {
|
else if (0 == ptload1lo) {
|
||||||
ptload1lo = x.offset;
|
ptload1lo = x.offset;
|
||||||
|
ptload1sz = x.size;
|
||||||
}
|
}
|
||||||
ui_total_passes++;
|
ui_total_passes++;
|
||||||
} else {
|
|
||||||
if (nx++ == 0)
|
|
||||||
ui_total_passes++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ptload0hi < ptload1lo)
|
if (0!=ptload1sz && ptload0hi < ptload1lo)
|
||||||
ui_total_passes++;
|
ui_total_passes++;
|
||||||
|
|
||||||
// compress extents
|
// compress extents
|
||||||
unsigned total_in = 0;
|
unsigned total_in = 0;
|
||||||
unsigned total_out = 0;
|
unsigned total_out = 0;
|
||||||
|
|
||||||
|
ui_pass = -1; // Compressing Elf headers is invisible to UI.
|
||||||
x.offset = 0;
|
x.offset = 0;
|
||||||
x.size = sizeof(Elf_LE32_Ehdr) + sz_phdrs;
|
x.size = sizeof(Elf_LE32_Ehdr) + sz_phdrs;
|
||||||
ui_pass = -1;
|
{
|
||||||
packExtent(x, fo, total_in, total_out);
|
int const old_level = ph.level; ph.level = 10;
|
||||||
ui_pass = 0;
|
packExtent(x, total_in, total_out, 0, fo);
|
||||||
|
ph.level = old_level;
|
||||||
|
}
|
||||||
|
|
||||||
nx = 0;
|
ui_pass = 0;
|
||||||
|
ft.addvalue = 0;
|
||||||
|
|
||||||
|
int nx = 0;
|
||||||
for (k = 0; k < ehdri.e_phnum; ++k) if (PT_LOAD==phdri[k].p_type) {
|
for (k = 0; k < ehdri.e_phnum; ++k) if (PT_LOAD==phdri[k].p_type) {
|
||||||
|
if (ft.id < 0x40) {
|
||||||
|
// FIXME: ?? ft.addvalue = phdri[k].p_vaddr;
|
||||||
|
}
|
||||||
x.offset = phdri[k].p_offset;
|
x.offset = phdri[k].p_offset;
|
||||||
x.size = phdri[k].p_filesz;
|
x.size = phdri[k].p_filesz;
|
||||||
if (0 == nx) {
|
if (0 == nx) { // 1st PT_LOAD must cover Ehdr at 0==p_offset
|
||||||
x.offset += sizeof(Elf_LE32_Ehdr) + sz_phdrs;
|
unsigned const delta = sizeof(Elf_LE32_Ehdr) + sz_phdrs;
|
||||||
x.size -= sizeof(Elf_LE32_Ehdr) + sz_phdrs;
|
if (ft.id < 0x40) {
|
||||||
|
// FIXME: ?? ft.addvalue += delta;
|
||||||
}
|
}
|
||||||
packExtent(x, fo, total_in, total_out);
|
x.offset += delta;
|
||||||
|
x.size -= delta;
|
||||||
|
}
|
||||||
|
packExtent(x, total_in, total_out,
|
||||||
|
((Elf_LE32_Phdr::PF_X & phdri[k].p_flags)
|
||||||
|
? &ft : 0 ), fo );
|
||||||
++nx;
|
++nx;
|
||||||
}
|
}
|
||||||
if (ptload0hi < ptload1lo) { // alignment hole?
|
if (0!=ptload1sz && ptload0hi < ptload1lo) { // alignment hole?
|
||||||
x.offset = ptload0hi;
|
x.offset = ptload0hi;
|
||||||
x.size = ptload1lo - ptload0hi;
|
x.size = ptload1lo - ptload0hi;
|
||||||
packExtent(x, fo, total_in, total_out);
|
packExtent(x, total_in, total_out, 0, fo);
|
||||||
}
|
}
|
||||||
if ((off_t)total_in < file_size) { // non-PT_LOAD stuff
|
if ((off_t)total_in < file_size) { // non-PT_LOAD stuff
|
||||||
x.offset = total_in;
|
x.offset = total_in;
|
||||||
x.size = file_size - total_in;
|
x.size = file_size - total_in;
|
||||||
packExtent(x, fo, total_in, total_out);
|
packExtent(x, total_in, total_out, 0, fo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((off_t)total_in != file_size)
|
if ((off_t)total_in != file_size)
|
||||||
throwEOFException();
|
throwEOFException();
|
||||||
|
|
||||||
// write block end marker (uncompressed size 0)
|
|
||||||
fo->write("\x00\x00\x00\x00", 4);
|
|
||||||
|
|
||||||
// update header with totals
|
|
||||||
ph.u_len = total_in;
|
|
||||||
ph.c_len = total_out;
|
|
||||||
|
|
||||||
// write header
|
|
||||||
const int hsize = ph.getPackHeaderSize();
|
|
||||||
set_le32(obuf, ph.magic); // note: always le32
|
|
||||||
patchPackHeader(obuf, hsize);
|
|
||||||
fo->write(obuf, hsize);
|
|
||||||
|
|
||||||
// write overlay offset (needed for decompression)
|
|
||||||
set_native32(obuf, lsize);
|
|
||||||
fo->write(obuf, 4);
|
|
||||||
|
|
||||||
updateLoader(fo);
|
|
||||||
|
|
||||||
// finally check the compression ratio
|
|
||||||
if (!checkFinalCompressionRatio(fo))
|
|
||||||
throwNotCompressible();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PackLinuxI386elf::unpackExtent(unsigned wanted, OutputFile *fo,
|
void PackLinuxI386elf::unpackExtent(unsigned wanted, OutputFile *fo,
|
||||||
unsigned &total_in, unsigned &total_out,
|
unsigned &total_in, unsigned &total_out,
|
||||||
unsigned &c_adler, unsigned &u_adler)
|
unsigned &c_adler, unsigned &u_adler,
|
||||||
|
bool first_PF_X, unsigned szb_info
|
||||||
|
)
|
||||||
{
|
{
|
||||||
|
b_info hdr; memset(&hdr, 0, sizeof(hdr));
|
||||||
while (wanted) {
|
while (wanted) {
|
||||||
fi->readx(ibuf, 8);
|
fi->readx(&hdr, szb_info);
|
||||||
int const sz_unc = ph.u_len = get_native32(ibuf+0);
|
int const sz_unc = ph.u_len = get_native32(&hdr.sz_unc);
|
||||||
int const sz_cpr = ph.c_len = get_native32(ibuf+4);
|
int const sz_cpr = ph.c_len = get_native32(&hdr.sz_cpr);
|
||||||
|
ph.filter_cto = hdr.b_cto8;
|
||||||
|
|
||||||
if (sz_unc == 0) { // must never happen while 0!=wanted
|
if (sz_unc == 0) { // must never happen while 0!=wanted
|
||||||
throwCompressedDataViolation();
|
throwCompressedDataViolation();
|
||||||
@@ -391,15 +361,34 @@ void PackLinuxI386elf::unpackExtent(unsigned wanted, OutputFile *fo,
|
|||||||
int j = blocksize + OVERHEAD - sz_cpr;
|
int j = blocksize + OVERHEAD - sz_cpr;
|
||||||
fi->readx(ibuf+j, sz_cpr);
|
fi->readx(ibuf+j, sz_cpr);
|
||||||
// update checksum of compressed data
|
// update checksum of compressed data
|
||||||
c_adler = upx_adler32(c_adler, ibuf + j, sz_cpr);
|
c_adler = upx_adler32(ibuf + j, sz_cpr, c_adler);
|
||||||
// decompress
|
// decompress
|
||||||
if (sz_cpr < sz_unc)
|
if (sz_cpr < sz_unc)
|
||||||
{
|
{
|
||||||
decompress(ibuf+j, ibuf, false);
|
decompress(ibuf+j, ibuf, false);
|
||||||
|
if (12==szb_info) { // modern per-block filter
|
||||||
|
if (hdr.b_ftid) {
|
||||||
|
Filter ft(ph.level); // FIXME: ph.level for b_info?
|
||||||
|
ft.init(hdr.b_ftid, 0);
|
||||||
|
ft.cto = hdr.b_cto8;
|
||||||
|
ft.unfilter(ibuf, sz_unc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // ancient per-file filter
|
||||||
|
if (first_PF_X) { // Elf32_Ehdr is never filtered
|
||||||
|
first_PF_X = false; // but everything else might be
|
||||||
|
}
|
||||||
|
else if (ph.filter) {
|
||||||
|
Filter ft(ph.level);
|
||||||
|
ft.init(ph.filter, 0);
|
||||||
|
ft.cto = (unsigned char) ph.filter_cto;
|
||||||
|
ft.unfilter(ibuf, sz_unc);
|
||||||
|
}
|
||||||
|
}
|
||||||
j = 0;
|
j = 0;
|
||||||
}
|
}
|
||||||
// update checksum of uncompressed data
|
// update checksum of uncompressed data
|
||||||
u_adler = upx_adler32(u_adler, ibuf + j, sz_unc);
|
u_adler = upx_adler32(ibuf + j, sz_unc, u_adler);
|
||||||
total_in += sz_cpr;
|
total_in += sz_cpr;
|
||||||
total_out += sz_unc;
|
total_out += sz_unc;
|
||||||
// write block
|
// write block
|
||||||
@@ -417,6 +406,16 @@ void PackLinuxI386elf::unpack(OutputFile *fo)
|
|||||||
Elf_LE32_Ehdr *const ehdr = (Elf_LE32_Ehdr *)bufehdr;
|
Elf_LE32_Ehdr *const ehdr = (Elf_LE32_Ehdr *)bufehdr;
|
||||||
Elf_LE32_Phdr const *phdr = (Elf_LE32_Phdr *)(1+ehdr);
|
Elf_LE32_Phdr const *phdr = (Elf_LE32_Phdr *)(1+ehdr);
|
||||||
|
|
||||||
|
unsigned szb_info = sizeof(b_info);
|
||||||
|
{
|
||||||
|
fi->seek(0, SEEK_SET);
|
||||||
|
fi->readx(bufehdr, MAX_ELF_HDR);
|
||||||
|
unsigned const e_entry = get_native32(&ehdr->e_entry);
|
||||||
|
if (e_entry < 0x401180) { /* old style, 8-byte b_info */
|
||||||
|
szb_info = 2*sizeof(unsigned);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fi->seek(overlay_offset, SEEK_SET);
|
fi->seek(overlay_offset, SEEK_SET);
|
||||||
p_info hbuf;
|
p_info hbuf;
|
||||||
fi->readx(&hbuf, sizeof(hbuf));
|
fi->readx(&hbuf, sizeof(hbuf));
|
||||||
@@ -426,9 +425,11 @@ void PackLinuxI386elf::unpack(OutputFile *fo)
|
|||||||
throwCantUnpack("file header corrupted");
|
throwCantUnpack("file header corrupted");
|
||||||
|
|
||||||
ibuf.alloc(blocksize + OVERHEAD);
|
ibuf.alloc(blocksize + OVERHEAD);
|
||||||
fi->readx(ibuf, 2*4);
|
b_info bhdr; memset(&bhdr, 0, sizeof(bhdr));
|
||||||
ph.u_len = get_native32(0+ibuf);
|
fi->readx(&bhdr, szb_info);
|
||||||
ph.c_len = get_native32(4+ibuf);
|
ph.u_len = get_native32(&bhdr.sz_unc);
|
||||||
|
ph.c_len = get_native32(&bhdr.sz_cpr);
|
||||||
|
ph.filter_cto = bhdr.b_cto8;
|
||||||
|
|
||||||
// Uncompress Ehdr and Phdrs.
|
// Uncompress Ehdr and Phdrs.
|
||||||
fi->readx(ibuf, ph.c_len);
|
fi->readx(ibuf, ph.c_len);
|
||||||
@@ -436,12 +437,13 @@ void PackLinuxI386elf::unpack(OutputFile *fo)
|
|||||||
|
|
||||||
unsigned total_in = 0;
|
unsigned total_in = 0;
|
||||||
unsigned total_out = 0;
|
unsigned total_out = 0;
|
||||||
unsigned c_adler = upx_adler32(0, NULL, 0);
|
unsigned c_adler = upx_adler32(NULL, 0);
|
||||||
unsigned u_adler = upx_adler32(0, NULL, 0);
|
unsigned u_adler = upx_adler32(NULL, 0);
|
||||||
off_t ptload0hi=0, ptload1lo=0;
|
off_t ptload0hi=0, ptload1lo=0, ptload1sz=0;
|
||||||
|
|
||||||
// decompress PT_LOAD
|
// decompress PT_LOAD
|
||||||
fi->seek(- (off_t) (2*4 + ph.c_len), SEEK_CUR);
|
bool first_PF_X = true;
|
||||||
|
fi->seek(- (off_t) (szb_info + ph.c_len), SEEK_CUR);
|
||||||
for (unsigned j=0; j < ehdr->e_phnum; ++phdr, ++j) {
|
for (unsigned j=0; j < ehdr->e_phnum; ++phdr, ++j) {
|
||||||
if (PT_LOAD==phdr->p_type) {
|
if (PT_LOAD==phdr->p_type) {
|
||||||
if (0==ptload0hi) {
|
if (0==ptload0hi) {
|
||||||
@@ -449,31 +451,42 @@ void PackLinuxI386elf::unpack(OutputFile *fo)
|
|||||||
}
|
}
|
||||||
else if (0==ptload1lo) {
|
else if (0==ptload1lo) {
|
||||||
ptload1lo = phdr->p_offset;
|
ptload1lo = phdr->p_offset;
|
||||||
|
ptload1sz = phdr->p_filesz;
|
||||||
}
|
}
|
||||||
if (fo)
|
if (fo)
|
||||||
fo->seek(phdr->p_offset, SEEK_SET);
|
fo->seek(phdr->p_offset, SEEK_SET);
|
||||||
unpackExtent(phdr->p_filesz, fo, total_in, total_out, c_adler, u_adler);
|
if (Elf_LE32_Phdr::PF_X & phdr->p_flags) {
|
||||||
|
unpackExtent(phdr->p_filesz, fo, total_in, total_out,
|
||||||
|
c_adler, u_adler, first_PF_X, szb_info);
|
||||||
|
first_PF_X = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unpackExtent(phdr->p_filesz, fo, total_in, total_out,
|
||||||
|
c_adler, u_adler, false, szb_info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ptload0hi < ptload1lo) { // alignment hole?
|
if (0!=ptload1sz && ptload0hi < ptload1lo) { // alignment hole?
|
||||||
if (fo)
|
if (fo)
|
||||||
fo->seek(ptload0hi, SEEK_SET);
|
fo->seek(ptload0hi, SEEK_SET);
|
||||||
unpackExtent(ptload1lo - ptload0hi, fo, total_in, total_out, c_adler, u_adler);
|
unpackExtent(ptload1lo - ptload0hi, fo, total_in, total_out,
|
||||||
|
c_adler, u_adler, false, szb_info);
|
||||||
}
|
}
|
||||||
if (total_out != orig_file_size) { // non-PT_LOAD stuff
|
if (total_out != orig_file_size) { // non-PT_LOAD stuff
|
||||||
if (fo)
|
if (fo)
|
||||||
fo->seek(0, SEEK_END);
|
fo->seek(0, SEEK_END);
|
||||||
unpackExtent(orig_file_size - total_out, fo, total_in, total_out, c_adler, u_adler);
|
unpackExtent(orig_file_size - total_out, fo, total_in, total_out,
|
||||||
|
c_adler, u_adler, false, szb_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for end-of-file
|
// check for end-of-file
|
||||||
fi->readx(ibuf, 2*4);
|
fi->readx(&bhdr, szb_info);
|
||||||
unsigned const sz_unc = ph.u_len = get_native32(ibuf+0);
|
unsigned const sz_unc = ph.u_len = get_native32(&bhdr.sz_unc);
|
||||||
|
|
||||||
if (sz_unc == 0) { // uncompressed size 0 -> EOF
|
if (sz_unc == 0) { // uncompressed size 0 -> EOF
|
||||||
// note: magic is always stored le32
|
// note: magic is always stored le32
|
||||||
unsigned const sz_cpr = get_le32(ibuf+4);
|
unsigned const sz_cpr = get_le32(&bhdr.sz_cpr);
|
||||||
if (sz_cpr != UPX_MAGIC_LE32) // sz_cpr must be h->magic
|
if (sz_cpr != UPX_MAGIC_LE32) // sz_cpr must be h->magic
|
||||||
throwCompressedDataViolation();
|
throwCompressedDataViolation();
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-17
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
Copyright (C) 2000 John F. Reiser
|
Copyright (C) 2000-2002 John F. Reiser
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,11 +22,8 @@
|
|||||||
If not, write to the Free Software Foundation, Inc.,
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar John F. Reiser
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu jreiser@BitWagon.com
|
||||||
|
|
||||||
John F. Reiser
|
|
||||||
jreiser@BitWagon.com
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -44,12 +41,12 @@ class PackLinuxI386elf : public PackLinuxI386
|
|||||||
public:
|
public:
|
||||||
PackLinuxI386elf(InputFile *f);
|
PackLinuxI386elf(InputFile *f);
|
||||||
virtual ~PackLinuxI386elf();
|
virtual ~PackLinuxI386elf();
|
||||||
virtual int getVersion() const { return 11; }
|
virtual int getVersion() const { return 13; }
|
||||||
virtual int getFormat() const { return UPX_F_LINUX_ELF_i386; }
|
virtual int getFormat() const { return UPX_F_LINUX_ELF_i386; }
|
||||||
virtual const char *getName() const { return "linux/elf386"; }
|
virtual const char *getName() const { return "linux/elf386"; }
|
||||||
virtual const int *getFilters() const { return NULL; }
|
virtual const int *getFilters() const;
|
||||||
|
virtual int buildLoader(const Filter *);
|
||||||
|
|
||||||
virtual void pack(OutputFile *fo);
|
|
||||||
virtual void unpack(OutputFile *fo);
|
virtual void unpack(OutputFile *fo);
|
||||||
|
|
||||||
virtual bool canPack();
|
virtual bool canPack();
|
||||||
@@ -61,21 +58,23 @@ protected:
|
|||||||
off_t offset;
|
off_t offset;
|
||||||
off_t size;
|
off_t size;
|
||||||
};
|
};
|
||||||
virtual void packExtent(Extent const &x, OutputFile *fo,
|
virtual void packExtent(Extent const &x,
|
||||||
unsigned &total_in, unsigned &total_out);
|
unsigned &total_in, unsigned &total_out, Filter *, OutputFile *);
|
||||||
virtual void unpackExtent(unsigned wanted, OutputFile *fo,
|
virtual void unpackExtent(unsigned wanted, OutputFile *fo,
|
||||||
unsigned &total_in, unsigned &total_out,
|
unsigned &total_in, unsigned &total_out,
|
||||||
unsigned &c_adler, unsigned &u_adler);
|
unsigned &c_adler, unsigned &u_adler,
|
||||||
|
bool first_PF_X, unsigned szb_info );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual const upx_byte *getLoader() const;
|
virtual void pack1(OutputFile *, Filter &); // generate executable header
|
||||||
virtual int getLoaderSize() const;
|
virtual void pack2(OutputFile *, Filter &); // append compressed data
|
||||||
|
|
||||||
virtual void patchLoader();
|
virtual void patchLoader();
|
||||||
virtual void updateLoader(OutputFile *);
|
|
||||||
|
|
||||||
Elf_LE32_Ehdr ehdri; // from input file
|
Elf_LE32_Ehdr ehdri; // from input file
|
||||||
Elf_LE32_Phdr *phdri; // for input file
|
Elf_LE32_Phdr *phdri; // for input file
|
||||||
|
unsigned sz_phdrs; // sizeof Phdr[]
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,470 @@
|
|||||||
|
/* p_lx_exc.cpp --
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
|
Copyright (C) 2001-2002 John F. Reiser
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar John F. Reiser
|
||||||
|
markus@oberhumer.com ml1050@cdata.tvnet.hu jreiser@BitWagon.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "conf.h"
|
||||||
|
|
||||||
|
#include "file.h"
|
||||||
|
#include "filter.h"
|
||||||
|
#include "linker.h"
|
||||||
|
#include "packer.h"
|
||||||
|
#include "p_elf.h"
|
||||||
|
#include "p_unix.h"
|
||||||
|
#include "p_lx_exc.h"
|
||||||
|
|
||||||
|
#define PT_LOAD Elf_LE32_Phdr::PT_LOAD
|
||||||
|
#define PT_DYNAMIC Elf_LE32_Phdr::PT_DYNAMIC
|
||||||
|
#define DT_NULL Elf_LE32_Dyn::DT_NULL
|
||||||
|
#define DT_NEEDED Elf_LE32_Dyn::DT_NEEDED
|
||||||
|
#define DT_STRTAB Elf_LE32_Dyn::DT_STRTAB
|
||||||
|
#define DT_STRSZ Elf_LE32_Dyn::DT_STRSZ
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// linux/386 (generic "execve" format)
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
static const
|
||||||
|
#include "stub/l_lx_exec86.h"
|
||||||
|
static const
|
||||||
|
#include "stub/fold_exec86.h"
|
||||||
|
|
||||||
|
|
||||||
|
const int *PackLinuxI386::getCompressionMethods(int method, int level) const
|
||||||
|
{
|
||||||
|
return Packer::getDefaultCompressionMethods_le32(method, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
const int *PackLinuxI386::getFilters() const
|
||||||
|
{
|
||||||
|
static const int filters[] = {
|
||||||
|
#if 1
|
||||||
|
0x26, 0x24, 0x11, 0x14, 0x13, 0x16, 0x25, 0x15, 0x12,
|
||||||
|
#else
|
||||||
|
0x49, 0x46,
|
||||||
|
0x83, 0x86, 0x80, 0x84, 0x87, 0x81, 0x82, 0x85,
|
||||||
|
0x24, 0x16, 0x13, 0x14, 0x11, 0x25, 0x15, 0x12,
|
||||||
|
#endif
|
||||||
|
-1 };
|
||||||
|
return filters;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PackLinuxI386::generateElfHdr(
|
||||||
|
OutputFile *const fo,
|
||||||
|
void const *const proto,
|
||||||
|
unsigned const brka
|
||||||
|
)
|
||||||
|
{
|
||||||
|
cprElfHdr1 *const h1 = (cprElfHdr1 *)&elfout;
|
||||||
|
cprElfHdr2 *const h2 = (cprElfHdr2 *)&elfout;
|
||||||
|
memcpy(h2, proto, sizeof(*h2));
|
||||||
|
|
||||||
|
assert(h2->ehdr.e_phoff == sizeof(Elf_LE32_Ehdr));
|
||||||
|
assert(h2->ehdr.e_shoff == 0);
|
||||||
|
assert(h2->ehdr.e_ehsize == sizeof(Elf_LE32_Ehdr));
|
||||||
|
assert(h2->ehdr.e_phentsize == sizeof(Elf_LE32_Phdr));
|
||||||
|
assert(h2->ehdr.e_shnum == 0);
|
||||||
|
|
||||||
|
#if 0 //{
|
||||||
|
unsigned identsize;
|
||||||
|
char const *const ident = getIdentstr(&identsize);
|
||||||
|
#endif //}
|
||||||
|
h2->phdr[0].p_filesz = sizeof(*h2); // + identsize;
|
||||||
|
h2->phdr[0].p_memsz = h2->phdr[0].p_filesz;
|
||||||
|
|
||||||
|
// Info for OS kernel to set the brk()
|
||||||
|
if (brka) {
|
||||||
|
h2->phdr[1].p_type = PT_LOAD; // be sure
|
||||||
|
h2->phdr[1].p_offset = 0xfff&brka;
|
||||||
|
h2->phdr[1].p_vaddr = brka;
|
||||||
|
h2->phdr[1].p_paddr = brka;
|
||||||
|
h2->phdr[1].p_filesz = 0;
|
||||||
|
h2->phdr[1].p_memsz = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ph.format==UPX_F_LINUX_i386 ) {
|
||||||
|
assert(h1->ehdr.e_phnum==1);
|
||||||
|
memset(&h1->linfo, 0, sizeof(h1->linfo));
|
||||||
|
fo->write(h1, sizeof(*h1));
|
||||||
|
}
|
||||||
|
else if (ph.format==UPX_F_LINUX_ELF_i386) {
|
||||||
|
assert(h2->ehdr.e_phnum==2);
|
||||||
|
memset(&h2->linfo, 0, sizeof(h2->linfo));
|
||||||
|
fo->write(h2, sizeof(*h2));
|
||||||
|
}
|
||||||
|
else if (ph.format==UPX_F_LINUX_SH_i386) {
|
||||||
|
assert(h2->ehdr.e_phnum==1);
|
||||||
|
h2->ehdr.e_phnum = 2;
|
||||||
|
memset(&h2->linfo, 0, sizeof(h2->linfo));
|
||||||
|
fo->write(h2, sizeof(*h2));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert(false); // unknown ph.format, PackUnix::generateElfHdr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PackLinuxI386::pack1(OutputFile *fo, Filter &)
|
||||||
|
{
|
||||||
|
// create a pseudo-unique program id for our paranoid stub
|
||||||
|
progid = getRandomId();
|
||||||
|
|
||||||
|
generateElfHdr(fo, linux_i386exec_fold, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PackLinuxI386::pack4(OutputFile *fo, Filter &ft)
|
||||||
|
{
|
||||||
|
overlay_offset = sizeof(elfout.ehdr) +
|
||||||
|
(elfout.ehdr.e_phentsize * elfout.ehdr.e_phnum) +
|
||||||
|
sizeof(l_info) +
|
||||||
|
((elfout.ehdr.e_phnum==3) ? elfout.phdr[2].p_memsz : 0) ;
|
||||||
|
super::pack4(fo, ft); // write PackHeader and overlay_offset
|
||||||
|
|
||||||
|
elfout.phdr[0].p_filesz = fo->getBytesWritten();
|
||||||
|
|
||||||
|
#define PAGE_MASK (~0<<12)
|
||||||
|
// pre-calculate for benefit of runtime disappearing act via munmap()
|
||||||
|
elfout.phdr[0].p_memsz = PAGE_MASK & (~PAGE_MASK + elfout.phdr[0].p_filesz);
|
||||||
|
#undef PAGE_MASK
|
||||||
|
|
||||||
|
// rewrite Elf header
|
||||||
|
fo->seek(0, SEEK_SET);
|
||||||
|
fo->rewrite(&elfout, sizeof(elfout.ehdr) +
|
||||||
|
elfout.ehdr.e_phnum * sizeof(elfout.phdr[0]) +
|
||||||
|
sizeof(l_info) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned
|
||||||
|
umax(unsigned a, unsigned b)
|
||||||
|
{
|
||||||
|
if (a <= b) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PackLinuxI386::buildLinuxLoader(
|
||||||
|
upx_byte const *const proto,
|
||||||
|
unsigned const szproto,
|
||||||
|
upx_byte const *const fold,
|
||||||
|
unsigned const szfold,
|
||||||
|
Filter const *ft
|
||||||
|
)
|
||||||
|
{
|
||||||
|
initLoader(proto, szproto);
|
||||||
|
|
||||||
|
cprElfHdr1 const *const hf = (cprElfHdr1 const *)fold;
|
||||||
|
unsigned const fold_hdrlen = umax(0x80, sizeof(hf->ehdr) +
|
||||||
|
hf->ehdr.e_phentsize * hf->ehdr.e_phnum + sizeof(l_info) );
|
||||||
|
struct b_info h; memset(&h, 0, sizeof(h));
|
||||||
|
h.sz_unc = szfold - fold_hdrlen;
|
||||||
|
h.b_method = (unsigned char) ph.method;
|
||||||
|
h.b_ftid = (unsigned char) ph.filter;
|
||||||
|
h.b_cto8 = (unsigned char) ph.filter_cto;
|
||||||
|
unsigned char const *const uncLoader = fold_hdrlen + fold;
|
||||||
|
|
||||||
|
unsigned char *const cprLoader = new unsigned char[sizeof(h) + h.sz_unc];
|
||||||
|
int r = upx_compress(uncLoader, h.sz_unc, sizeof(h) + cprLoader, &h.sz_cpr,
|
||||||
|
NULL, ph.method, 10, NULL, NULL );
|
||||||
|
if (r != UPX_E_OK || h.sz_cpr >= h.sz_unc)
|
||||||
|
throwInternalError("loader compression failed");
|
||||||
|
memcpy(cprLoader, &h, sizeof(h));
|
||||||
|
|
||||||
|
// This adds the definition to the "library", to be used later.
|
||||||
|
linker->addSection("FOLDEXEC", cprLoader, sizeof(h) + h.sz_cpr);
|
||||||
|
delete cprLoader;
|
||||||
|
|
||||||
|
n_mru = ft->n_mru;
|
||||||
|
|
||||||
|
// Here is a quick summary of the format of the output file:
|
||||||
|
linker->setLoaderAlignOffset(
|
||||||
|
// Elf32_Edhr
|
||||||
|
sizeof(elfout.ehdr) +
|
||||||
|
// Elf32_Phdr: 1 for exec86, 2 for sh86, 3 for elf86
|
||||||
|
(elfout.ehdr.e_phentsize * elfout.ehdr.e_phnum) +
|
||||||
|
// checksum UPX! lsize version format
|
||||||
|
sizeof(l_info) +
|
||||||
|
// PT_DYNAMIC with DT_NEEDED "forwarded" from original file
|
||||||
|
((elfout.ehdr.e_phnum==3) ? elfout.phdr[2].p_memsz : 0) +
|
||||||
|
// p_progid, p_filesize, p_blocksize
|
||||||
|
sizeof(p_info) +
|
||||||
|
// compressed data
|
||||||
|
b_len + ph.c_len );
|
||||||
|
// entry to stub
|
||||||
|
addLoader("LEXEC000", 0);
|
||||||
|
|
||||||
|
if (ft->id) {
|
||||||
|
if (ph.format==UPX_F_LINUX_ELF_i386) { // decompr, unfilter are separate
|
||||||
|
addLoader("LXUNF000", 0);
|
||||||
|
addLoader("LXUNF002", 0);
|
||||||
|
if (0x80==(ft->id & 0xF0)) {
|
||||||
|
if (256==n_mru) {
|
||||||
|
addLoader("MRUBYTE0", 0);
|
||||||
|
}
|
||||||
|
else if (n_mru) {
|
||||||
|
addLoader("LXMRU005", 0);
|
||||||
|
}
|
||||||
|
if (n_mru) {
|
||||||
|
addLoader("LXMRU006", 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addLoader("LXMRU007", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (0x40==(ft->id & 0xF0)) {
|
||||||
|
addLoader("LXUNF008", 0);
|
||||||
|
}
|
||||||
|
addLoader("LXUNF010", 0);
|
||||||
|
}
|
||||||
|
if (n_mru) {
|
||||||
|
addLoader("LEXEC009", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addLoader("LEXEC010", 0);
|
||||||
|
addLoader(getDecompressor(), 0);
|
||||||
|
addLoader("LEXEC015", 0);
|
||||||
|
if (ft->id) {
|
||||||
|
if (ph.format==UPX_F_LINUX_ELF_i386) { // decompr, unfilter are separate
|
||||||
|
if (0x80!=(ft->id & 0xF0)) {
|
||||||
|
addLoader("LXUNF042", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // decompr, unfilter not separate
|
||||||
|
if (0x80==(ft->id & 0xF0)) {
|
||||||
|
addLoader("LEXEC110", 0);
|
||||||
|
if (n_mru) {
|
||||||
|
addLoader("LEXEC100", 0);
|
||||||
|
}
|
||||||
|
// bug in APP: jmp and label must be in same .asx/.asy
|
||||||
|
addLoader("LEXEC016", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addFilter32(ft->id);
|
||||||
|
if (ph.format==UPX_F_LINUX_ELF_i386) { // decompr, unfilter are separate
|
||||||
|
if (0x80==(ft->id & 0xF0)) {
|
||||||
|
if (0==n_mru) {
|
||||||
|
addLoader("LXMRU058", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addLoader("LXUNF035", 0);
|
||||||
|
}
|
||||||
|
else { // decompr always unfilters
|
||||||
|
addLoader("LEXEC017", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addLoader("IDENTSTR", 0);
|
||||||
|
addLoader("LEXEC020", 0);
|
||||||
|
addLoader("FOLDEXEC", 0);
|
||||||
|
|
||||||
|
char *ptr_cto = (char *)const_cast<unsigned char *>(getLoader());
|
||||||
|
int sz_cto = getLoaderSize();
|
||||||
|
if (0x20==(ft->id & 0xF0) || 0x30==(ft->id & 0xF0)) { // push byte '?' ; cto8
|
||||||
|
patch_le16(ptr_cto, sz_cto, "\x6a?", 0x6a + (ft->cto << 8));
|
||||||
|
checkPatch(NULL, 0, 0, 0); // reset
|
||||||
|
}
|
||||||
|
// PackHeader and overlay_offset at the end of the output file,
|
||||||
|
// after the compressed data.
|
||||||
|
|
||||||
|
return getLoaderSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PackLinuxI386::buildLoader(Filter const *ft)
|
||||||
|
{
|
||||||
|
unsigned const sz_fold = sizeof(linux_i386exec_fold);
|
||||||
|
MemBuffer buf(sz_fold);
|
||||||
|
memcpy(buf, linux_i386exec_fold, sz_fold);
|
||||||
|
|
||||||
|
// patch loader
|
||||||
|
// note: we only can use /proc/<pid>/fd when exetype > 0.
|
||||||
|
// also, we sleep much longer when compressing a script.
|
||||||
|
checkPatch(NULL, 0, 0, 0); // reset
|
||||||
|
patch_le32(buf,sz_fold,"UPX4",exetype > 0 ? 3 : 15); // sleep time
|
||||||
|
patch_le32(buf,sz_fold,"UPX3",progid);
|
||||||
|
patch_le32(buf,sz_fold,"UPX2",exetype > 0 ? 0 : 0x7fffffff);
|
||||||
|
|
||||||
|
// get fresh filter
|
||||||
|
Filter fold_ft = *ft;
|
||||||
|
fold_ft.init(ft->id, ft->addvalue);
|
||||||
|
int preferred_ctos[2] = {ft->cto, -1};
|
||||||
|
fold_ft.preferred_ctos = preferred_ctos;
|
||||||
|
|
||||||
|
// filter
|
||||||
|
optimizeFilter(&fold_ft, buf, sz_fold);
|
||||||
|
bool success = fold_ft.filter(buf + sizeof(cprElfHdr2), sz_fold - sizeof(cprElfHdr2));
|
||||||
|
(void)success;
|
||||||
|
|
||||||
|
return buildLinuxLoader(
|
||||||
|
linux_i386exec_loader, sizeof(linux_i386exec_loader),
|
||||||
|
buf, sz_fold, ft );
|
||||||
|
}
|
||||||
|
|
||||||
|
int PackLinuxI386::getLoaderPrefixSize() const
|
||||||
|
{
|
||||||
|
return 116;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// some ELF utitlity functions
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
// basic check of an Linux ELF Ehdr
|
||||||
|
int PackLinuxI386::checkEhdr(const Elf_LE32_Ehdr *ehdr) const
|
||||||
|
{
|
||||||
|
const unsigned char * const buf = ehdr->e_ident;
|
||||||
|
|
||||||
|
if (memcmp(buf, "\x7f\x45\x4c\x46\x01\x01\x01", 7)) // ELF 32-bit LSB
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// now check the ELF header
|
||||||
|
if (!memcmp(buf+8, "FreeBSD", 7)) // branded
|
||||||
|
return 1;
|
||||||
|
if (ehdr->e_type != 2) // executable
|
||||||
|
return 2;
|
||||||
|
if (ehdr->e_machine != 3) // Intel 80386
|
||||||
|
return 3;
|
||||||
|
if (ehdr->e_version != 1) // version
|
||||||
|
return 4;
|
||||||
|
if (ehdr->e_phnum < 1)
|
||||||
|
return 5;
|
||||||
|
if (ehdr->e_phentsize != sizeof(Elf_LE32_Phdr))
|
||||||
|
return 6;
|
||||||
|
|
||||||
|
// check for Linux kernels
|
||||||
|
if (ehdr->e_entry == 0xC0100000) // uncompressed vmlinux
|
||||||
|
return 1000;
|
||||||
|
if (ehdr->e_entry == 0x00001000) // compressed vmlinux
|
||||||
|
return 1001;
|
||||||
|
if (ehdr->e_entry == 0x00100000) // compressed bvmlinux
|
||||||
|
return 1002;
|
||||||
|
|
||||||
|
// FIXME: add more checks for kernels
|
||||||
|
|
||||||
|
// FIXME: add special checks for other ELF i386 formats, like
|
||||||
|
// NetBSD, OpenBSD, Solaris, ....
|
||||||
|
|
||||||
|
// success
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
off_t PackLinuxI386::getbrk(const Elf_LE32_Phdr *phdr, int e_phnum) const
|
||||||
|
{
|
||||||
|
off_t brka = 0;
|
||||||
|
for (int j = 0; j < e_phnum; ++phdr, ++j) {
|
||||||
|
if (phdr->PT_LOAD == phdr->p_type) {
|
||||||
|
off_t b = phdr->p_vaddr + phdr->p_memsz;
|
||||||
|
if (b > brka)
|
||||||
|
brka = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return brka;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
bool PackLinuxI386::canPack()
|
||||||
|
{
|
||||||
|
if (exetype != 0)
|
||||||
|
return super::canPack();
|
||||||
|
|
||||||
|
Elf_LE32_Ehdr ehdr;
|
||||||
|
unsigned char *buf = ehdr.e_ident;
|
||||||
|
|
||||||
|
fi->readx(&ehdr, sizeof(ehdr));
|
||||||
|
fi->seek(0, SEEK_SET);
|
||||||
|
|
||||||
|
exetype = 0;
|
||||||
|
const unsigned l = get_le32(buf);
|
||||||
|
|
||||||
|
int elf = checkEhdr(&ehdr);
|
||||||
|
if (elf >= 0)
|
||||||
|
{
|
||||||
|
// NOTE: ELF executables are now handled by p_lx_elf.cpp,
|
||||||
|
// so we only handle them here if force_execve
|
||||||
|
if (elf == 0 && opt->unix.force_execve)
|
||||||
|
exetype = 1;
|
||||||
|
}
|
||||||
|
else if (l == 0x00640107 || l == 0x00640108 || l == 0x0064010b || l == 0x006400cc)
|
||||||
|
{
|
||||||
|
// OMAGIC / NMAGIC / ZMAGIC / QMAGIC
|
||||||
|
exetype = 2;
|
||||||
|
// FIXME: N_TRSIZE, N_DRSIZE
|
||||||
|
// FIXME: check for aout shared libraries
|
||||||
|
}
|
||||||
|
#if defined(__linux__)
|
||||||
|
// only compress scripts when running under Linux
|
||||||
|
else if (!memcmp(buf, "#!/", 3)) // #!/bin/sh
|
||||||
|
exetype = -1;
|
||||||
|
else if (!memcmp(buf, "#! /", 4)) // #! /bin/sh
|
||||||
|
exetype = -1;
|
||||||
|
else if (!memcmp(buf, "\xca\xfe\xba\xbe", 4)) // Java bytecode
|
||||||
|
exetype = -2;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return super::canPack();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PackLinuxI386::patchLoader() { }
|
||||||
|
|
||||||
|
|
||||||
|
void PackLinuxI386::patchLoaderChecksum()
|
||||||
|
{
|
||||||
|
unsigned char *const ptr = const_cast<unsigned char *>(getLoader());
|
||||||
|
l_info *const lp = (l_info *)(sizeof(elfout.ehdr) +
|
||||||
|
(elfout.ehdr.e_phnum * elfout.ehdr.e_phentsize) + (char *)&elfout );
|
||||||
|
// checksum for loader + p_info
|
||||||
|
lp->l_checksum = 0;
|
||||||
|
lp->l_magic = UPX_ELF_MAGIC;
|
||||||
|
lp->l_lsize = (unsigned short) lsize;
|
||||||
|
lp->l_version = (unsigned char) ph.version;
|
||||||
|
lp->l_format = (unsigned char) ph.format;
|
||||||
|
// INFO: lp->l_checksum is currently unused
|
||||||
|
lp->l_checksum = upx_adler32(ptr, lsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PackLinuxI386::updateLoader(OutputFile *fo)
|
||||||
|
{
|
||||||
|
elfout.ehdr.e_entry = fo->getBytesWritten() + elfout.phdr[0].p_vaddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
vi:ts=4:et
|
||||||
|
*/
|
||||||
|
|
||||||
+118
@@ -0,0 +1,118 @@
|
|||||||
|
/* p_lx_exc.h --
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __UPX_P_LX_EXC_H
|
||||||
|
#define __UPX_P_LX_EXC_H
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// linux/386 (generic "execve" format)
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
class PackLinuxI386 : public PackUnixLe32
|
||||||
|
{
|
||||||
|
typedef PackUnixLe32 super;
|
||||||
|
public:
|
||||||
|
PackLinuxI386(InputFile *f) : super(f) { }
|
||||||
|
virtual void generateElfHdr(
|
||||||
|
OutputFile *,
|
||||||
|
void const *proto,
|
||||||
|
unsigned brka
|
||||||
|
);
|
||||||
|
virtual int getFormat() const { return UPX_F_LINUX_i386; }
|
||||||
|
virtual const char *getName() const { return "linux/386"; }
|
||||||
|
virtual const int *getCompressionMethods(int method, int level) const;
|
||||||
|
virtual const int *getFilters() const;
|
||||||
|
virtual int buildLoader(const Filter *);
|
||||||
|
|
||||||
|
virtual bool canPack();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void pack1(OutputFile *, Filter &); // generate executable header
|
||||||
|
// virtual void pack2(OutputFile *, Filter &); // append compressed data
|
||||||
|
// virtual void pack3(OutputFile *, Filter &); // append loader
|
||||||
|
virtual void pack4(OutputFile *, Filter &); // append PackHeader
|
||||||
|
|
||||||
|
// loader util
|
||||||
|
virtual int getLoaderPrefixSize() const;
|
||||||
|
virtual int buildLinuxLoader(
|
||||||
|
upx_byte const *const proto, // assembly-only sections
|
||||||
|
unsigned const szproto,
|
||||||
|
upx_byte const *const fold, // linked assembly + C section
|
||||||
|
unsigned const szfold,
|
||||||
|
Filter const *ft
|
||||||
|
);
|
||||||
|
|
||||||
|
// patch util
|
||||||
|
virtual void patchLoader();
|
||||||
|
virtual void patchLoaderChecksum();
|
||||||
|
virtual void updateLoader(OutputFile *);
|
||||||
|
|
||||||
|
// ELF util
|
||||||
|
virtual int checkEhdr(const Elf_LE32_Ehdr *ehdr) const;
|
||||||
|
virtual off_t getbrk(const Elf_LE32_Phdr *phdr, int e_phnum) const;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
UPX_ELF_MAGIC = 0x5850557f // "\x7fUPX"
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned n_mru;
|
||||||
|
|
||||||
|
struct cprElfHdr1 {
|
||||||
|
struct Elf_LE32_Ehdr ehdr;
|
||||||
|
struct Elf_LE32_Phdr phdr[1];
|
||||||
|
struct PackUnix::l_info linfo;
|
||||||
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
|
struct cprElfHdr2 {
|
||||||
|
struct Elf_LE32_Ehdr ehdr;
|
||||||
|
struct Elf_LE32_Phdr phdr[2];
|
||||||
|
struct PackUnix::l_info linfo;
|
||||||
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
|
struct cprElfHdr3 {
|
||||||
|
struct Elf_LE32_Ehdr ehdr;
|
||||||
|
struct Elf_LE32_Phdr phdr[3];
|
||||||
|
struct PackUnix::l_info linfo;
|
||||||
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
|
cprElfHdr3 elfout;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* already included */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
vi:ts=4:et
|
||||||
|
*/
|
||||||
|
|
||||||
+13
-14
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
Copyright (C) 2000 John F. Reiser
|
Copyright (C) 2000-2002 John F. Reiser
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,11 +22,8 @@
|
|||||||
If not, write to the Free Software Foundation, Inc.,
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar John F. Reiser
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu jreiser@BitWagon.com
|
||||||
|
|
||||||
John F. Reiser
|
|
||||||
jreiser@BitWagon.com
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -36,6 +33,7 @@
|
|||||||
#include "packer.h"
|
#include "packer.h"
|
||||||
#include "p_elf.h"
|
#include "p_elf.h"
|
||||||
#include "p_unix.h"
|
#include "p_unix.h"
|
||||||
|
#include "p_lx_exc.h"
|
||||||
#include "p_lx_elf.h"
|
#include "p_lx_elf.h"
|
||||||
#include "p_lx_sep.h"
|
#include "p_lx_sep.h"
|
||||||
|
|
||||||
@@ -44,7 +42,8 @@
|
|||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#define SCRIPT_SIZE (opt->unix.SCRIPT_MAX + sizeof(l_info))
|
//#define SCRIPT_SIZE (opt->unix.SCRIPT_MAX + sizeof(l_info))
|
||||||
|
#define SCRIPT_SIZE (32 + sizeof(l_info))
|
||||||
|
|
||||||
const upx_byte *PackLinuxI386sep::getLoader() const
|
const upx_byte *PackLinuxI386sep::getLoader() const
|
||||||
{
|
{
|
||||||
@@ -55,12 +54,12 @@ const upx_byte *PackLinuxI386sep::getLoader() const
|
|||||||
if (0==name) {
|
if (0==name) {
|
||||||
name = "/usr/local/lib/upxX";
|
name = "/usr/local/lib/upxX";
|
||||||
}
|
}
|
||||||
sprintf(script, "#!%s\n", name);
|
upx_snprintf(script, sizeof(script), "#!%s\n", name);
|
||||||
if (M_IS_NRV2B(opt->method)) {
|
if (M_IS_NRV2B(ph.method)) {
|
||||||
script[strlen(script)-2] = 'b';
|
script[strlen(script)-2] = 'b';
|
||||||
return (upx_byte const *)script;
|
return (upx_byte const *)script;
|
||||||
}
|
}
|
||||||
if (M_IS_NRV2D(opt->method)) {
|
if (M_IS_NRV2D(ph.method)) {
|
||||||
script[strlen(script)-2] = 'd';
|
script[strlen(script)-2] = 'd';
|
||||||
return (upx_byte const *)script;
|
return (upx_byte const *)script;
|
||||||
}
|
}
|
||||||
@@ -69,9 +68,9 @@ const upx_byte *PackLinuxI386sep::getLoader() const
|
|||||||
|
|
||||||
int PackLinuxI386sep::getLoaderSize() const
|
int PackLinuxI386sep::getLoaderSize() const
|
||||||
{
|
{
|
||||||
if (M_IS_NRV2B(opt->method))
|
if (M_IS_NRV2B(ph.method))
|
||||||
return SCRIPT_SIZE;
|
return SCRIPT_SIZE;
|
||||||
if (M_IS_NRV2D(opt->method))
|
if (M_IS_NRV2D(ph.method))
|
||||||
return SCRIPT_SIZE;
|
return SCRIPT_SIZE;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
Copyright (C) 2000 John F. Reiser
|
Copyright (C) 2000-2002 John F. Reiser
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,8 +22,8 @@
|
|||||||
If not, write to the Free Software Foundation, Inc.,
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
John F. Reiser
|
Markus F.X.J. Oberhumer Laszlo Molnar John F. Reiser
|
||||||
jreiser@BitWagon.com
|
markus@oberhumer.com ml1050@cdata.tvnet.hu jreiser@BitWagon.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+58
-135
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
Copyright (C) 2000 John F. Reiser
|
Copyright (C) 2000-2002 John F. Reiser
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,128 +22,71 @@
|
|||||||
If not, write to the Free Software Foundation, Inc.,
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar John F. Reiser
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu jreiser@BitWagon.com
|
||||||
|
|
||||||
John F. Reiser
|
|
||||||
jreiser@BitWagon.com
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
#include "filter.h"
|
||||||
#include "packer.h"
|
#include "packer.h"
|
||||||
#include "p_elf.h"
|
#include "p_elf.h"
|
||||||
#include "p_unix.h"
|
#include "p_unix.h"
|
||||||
|
#include "p_lx_exc.h"
|
||||||
#include "p_lx_sh.h"
|
#include "p_lx_sh.h"
|
||||||
|
|
||||||
|
#define PT_LOAD Elf_LE32_Phdr::PT_LOAD
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
static const
|
static const
|
||||||
#include "stub/l_sh_n2b.h"
|
#include "stub/l_lx_sh86.h"
|
||||||
static const
|
static const
|
||||||
#include "stub/l_sh_n2d.h"
|
#include "stub/fold_sh86.h"
|
||||||
|
|
||||||
|
|
||||||
|
PackLinuxI386sh::PackLinuxI386sh(InputFile *f) :
|
||||||
|
super(f), o_shname(0), l_shname(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
PackLinuxI386sh::~PackLinuxI386sh()
|
PackLinuxI386sh::~PackLinuxI386sh()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PackLinuxI386sh::PackLinuxI386sh(InputFile *f)
|
int
|
||||||
:super(f)
|
PackLinuxI386sh::buildLoader(Filter const *ft)
|
||||||
,o_shname(0)
|
|
||||||
,l_shname(0)
|
|
||||||
{
|
{
|
||||||
|
unsigned const sz_fold = sizeof(linux_i386sh_fold);
|
||||||
|
MemBuffer buf(sz_fold);
|
||||||
|
memcpy(buf, linux_i386sh_fold, sz_fold);
|
||||||
|
|
||||||
|
checkPatch(NULL, 0, 0, 0); // reset
|
||||||
|
patch_le32(buf,sz_fold,"UPX3",l_shname);
|
||||||
|
patch_le32(buf,sz_fold,"UPX2",o_shname);
|
||||||
|
|
||||||
|
// get fresh filter
|
||||||
|
Filter fold_ft = *ft;
|
||||||
|
fold_ft.init(ft->id, ft->addvalue);
|
||||||
|
int preferred_ctos[2] = {ft->cto, -1};
|
||||||
|
fold_ft.preferred_ctos = preferred_ctos;
|
||||||
|
|
||||||
|
// filter
|
||||||
|
optimizeFilter(&fold_ft, buf, sz_fold);
|
||||||
|
bool success = fold_ft.filter(buf + sizeof(cprElfHdr2), sz_fold - sizeof(cprElfHdr2));
|
||||||
|
UNUSED(success);
|
||||||
|
|
||||||
|
return buildLinuxLoader(
|
||||||
|
linux_i386sh_loader, sizeof(linux_i386sh_loader),
|
||||||
|
buf, sz_fold, ft );
|
||||||
}
|
}
|
||||||
|
|
||||||
const upx_byte *PackLinuxI386sh::getLoader() const
|
void PackLinuxI386sh::patchLoader() { }
|
||||||
{
|
|
||||||
if (M_IS_NRV2B(opt->method))
|
|
||||||
return linux_i386sh_nrv2b_loader;
|
|
||||||
if (M_IS_NRV2D(opt->method))
|
|
||||||
return linux_i386sh_nrv2d_loader;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PackLinuxI386sh::getLoaderSize() const
|
|
||||||
{
|
|
||||||
if (0 != lsize) {
|
|
||||||
return lsize;
|
|
||||||
}
|
|
||||||
if (M_IS_NRV2B(opt->method))
|
|
||||||
return sizeof(linux_i386sh_nrv2b_loader);
|
|
||||||
if (M_IS_NRV2D(opt->method))
|
|
||||||
return sizeof(linux_i386sh_nrv2d_loader);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline off_t max_off_t(off_t a, off_t b)
|
|
||||||
{
|
|
||||||
return a > b ? a : b;
|
|
||||||
}
|
|
||||||
|
|
||||||
static off_t getbrk(Elf_LE32_Phdr const *phdr, int e_phnum)
|
|
||||||
{
|
|
||||||
off_t brka = 0;
|
|
||||||
for (int j = 0; j < e_phnum; ++phdr, ++j) if (PT_LOAD==phdr->p_type) {
|
|
||||||
brka = max_off_t(brka, phdr->p_vaddr + phdr->p_memsz);
|
|
||||||
}
|
|
||||||
return brka;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PackLinuxI386sh::patchLoader()
|
|
||||||
{
|
|
||||||
lsize = getLoaderSize();
|
|
||||||
ehdri = (Elf_LE32_Ehdr *)(void *)loader;
|
|
||||||
Elf_LE32_Phdr *const phdri = (Elf_LE32_Phdr *)(1+ehdri);
|
|
||||||
|
|
||||||
patch_le32(loader,lsize,"UPX3",l_shname);
|
|
||||||
patch_le32(loader,lsize,"UPX2",o_shname);
|
|
||||||
|
|
||||||
// stub/scripts/setfold.pl puts address of 'fold_begin' in phdr[1].p_offset
|
|
||||||
off_t const fold_begin = phdri[1].p_offset;
|
|
||||||
assert(fold_begin > 0);
|
|
||||||
assert(fold_begin < (off_t)lsize);
|
|
||||||
MemBuffer cprLoader(lsize);
|
|
||||||
|
|
||||||
// compress compiled C-code portion of loader
|
|
||||||
upx_compress_config_t conf; memset(&conf, 0xff, sizeof(conf));
|
|
||||||
conf.c_flags = 0;
|
|
||||||
upx_uint result_buffer[16];
|
|
||||||
upx_uint cprLsize;
|
|
||||||
upx_compress(
|
|
||||||
loader + fold_begin, lsize - fold_begin,
|
|
||||||
cprLoader, &cprLsize,
|
|
||||||
0, // progress_callback_t ??
|
|
||||||
getCompressionMethod(), 9,
|
|
||||||
&conf,
|
|
||||||
result_buffer
|
|
||||||
);
|
|
||||||
set_le32(0+fold_begin+loader, lsize - fold_begin);
|
|
||||||
set_le32(4+fold_begin+loader, cprLsize);
|
|
||||||
memcpy( 8+fold_begin+loader, cprLoader, cprLsize);
|
|
||||||
lsize = 8 + fold_begin + cprLsize;
|
|
||||||
patchVersion(loader,lsize);
|
|
||||||
|
|
||||||
unsigned const brka = getbrk(phdri, ehdri->e_phnum);
|
|
||||||
phdri[1].p_offset = 0xfff&brka;
|
|
||||||
phdri[1].p_vaddr = brka;
|
|
||||||
phdri[1].p_paddr = brka;
|
|
||||||
phdri[1].p_filesz = 0;
|
|
||||||
phdri[1].p_memsz = 0;
|
|
||||||
|
|
||||||
// The beginning of our loader consists of a elf_hdr (52 bytes) and
|
|
||||||
// two sections elf_phdr (2 * 32 byte), so we have 12 free bytes
|
|
||||||
// from offset 116 to the program start at offset 128.
|
|
||||||
assert(ehdri->e_phoff == sizeof(Elf_LE32_Ehdr));
|
|
||||||
assert(ehdri->e_ehsize == sizeof(Elf_LE32_Ehdr));
|
|
||||||
assert(ehdri->e_phentsize == sizeof(Elf_LE32_Phdr));
|
|
||||||
assert(ehdri->e_phnum == 2);
|
|
||||||
assert(ehdri->e_shnum == 0);
|
|
||||||
assert(lsize > 128 && lsize < 4096);
|
|
||||||
|
|
||||||
patchLoaderChecksum();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool PackLinuxI386sh::getShellName(char *buf)
|
bool PackLinuxI386sh::getShellName(char *buf)
|
||||||
@@ -151,15 +94,16 @@ bool PackLinuxI386sh::getShellName(char *buf)
|
|||||||
exetype = -1;
|
exetype = -1;
|
||||||
l_shname = strcspn(buf, " \t\n\v\f\r");
|
l_shname = strcspn(buf, " \t\n\v\f\r");
|
||||||
buf[l_shname] = 0;
|
buf[l_shname] = 0;
|
||||||
char const *const basename = 1+strrchr(buf, '/');
|
|
||||||
static char const *const shname[] = { // known shells that accept "-c" arg
|
static char const *const shname[] = { // known shells that accept "-c" arg
|
||||||
"sh", "ash", "bsh", "csh", "ksh", "bash", "tcsh", "pdksh",
|
"ash", "bash", "bsh", "csh", "ksh", "pdksh", "sh", "tcsh", "zsh",
|
||||||
//"python", // FIXME: does python work ???
|
//"python", // FIXME: does python work ???
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
for (int j=0; 0 != shname[j]; ++j) {
|
const char *bname = strrchr(buf, '/');
|
||||||
if (0==strcmp(shname[j], basename)) {
|
if (bname == NULL)
|
||||||
o_shname += 3; // space for "-c\x00"
|
return false;
|
||||||
|
for (int j = 0; NULL != shname[j]; ++j) {
|
||||||
|
if (0 == strcmp(shname[j], bname + 1)) {
|
||||||
return super::canPack();
|
return super::canPack();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,9 +117,9 @@ bool PackLinuxI386sh::canPack()
|
|||||||
// only compress i386sh scripts when running under Linux
|
// only compress i386sh scripts when running under Linux
|
||||||
char buf[512];
|
char buf[512];
|
||||||
|
|
||||||
fi->readx(buf, 512);
|
fi->readx(buf, sizeof(buf));
|
||||||
fi->seek(0, SEEK_SET);
|
fi->seek(0, SEEK_SET);
|
||||||
buf[511] = 0;
|
buf[sizeof(buf) - 1] = 0;
|
||||||
if (!memcmp(buf, "#!/", 3)) { // #!/bin/sh
|
if (!memcmp(buf, "#!/", 3)) { // #!/bin/sh
|
||||||
o_shname = 2;
|
o_shname = 2;
|
||||||
return getShellName(&buf[o_shname]);
|
return getShellName(&buf[o_shname]);
|
||||||
@@ -189,33 +133,12 @@ bool PackLinuxI386sh::canPack()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PackLinuxI386sh::pack(OutputFile *fo)
|
void
|
||||||
|
PackLinuxI386sh::pack1(OutputFile *fo, Filter &)
|
||||||
{
|
{
|
||||||
#define PAGE_MASK (~0<<12)
|
generateElfHdr(fo, linux_i386sh_fold, 0x08048000);
|
||||||
opt->unix.blocksize = blocksize = file_size;
|
|
||||||
PackUnix::pack(fo);
|
|
||||||
|
|
||||||
// update loader
|
|
||||||
Elf_LE32_Phdr *const phdro = (Elf_LE32_Phdr *)(sizeof(Elf_LE32_Ehdr)+loader);
|
|
||||||
off_t const totlen = fo->getBytesWritten();
|
|
||||||
phdro[0].p_filesz = totlen;
|
|
||||||
phdro[0].p_memsz = PAGE_MASK & (~PAGE_MASK + totlen);
|
|
||||||
|
|
||||||
// Try to make brk() work by faking it for exec().
|
|
||||||
unsigned const brka = 0x08048000;
|
|
||||||
phdro[1].p_offset = 0xfff&brka;
|
|
||||||
phdro[1].p_vaddr = brka;
|
|
||||||
phdro[1].p_paddr = brka;
|
|
||||||
phdro[1].p_filesz = 0;
|
|
||||||
phdro[1].p_memsz = 0;
|
|
||||||
|
|
||||||
patchLoaderChecksum();
|
|
||||||
fo->seek(0, SEEK_SET);
|
|
||||||
fo->rewrite(loader, 0x80);
|
|
||||||
#undef PAGE_MASK
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
vi:ts=4:et
|
vi:ts=4:et
|
||||||
*/
|
*/
|
||||||
|
|||||||
+9
-14
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
Copyright (C) 2000 John F. Reiser
|
Copyright (C) 2000-2002 John F. Reiser
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,11 +22,8 @@
|
|||||||
If not, write to the Free Software Foundation, Inc.,
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar John F. Reiser
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu jreiser@BitWagon.com
|
||||||
|
|
||||||
John F. Reiser
|
|
||||||
jreiser@BitWagon.com
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -44,26 +41,24 @@ class PackLinuxI386sh : public PackLinuxI386
|
|||||||
public:
|
public:
|
||||||
PackLinuxI386sh(InputFile *f);
|
PackLinuxI386sh(InputFile *f);
|
||||||
virtual ~PackLinuxI386sh();
|
virtual ~PackLinuxI386sh();
|
||||||
virtual int getVersion() const { return 11; }
|
virtual int getVersion() const { return 13; }
|
||||||
virtual int getFormat() const { return UPX_F_LINUX_SH_i386; }
|
virtual int getFormat() const { return UPX_F_LINUX_SH_i386; }
|
||||||
virtual const char *getName() const { return "linux/sh386"; }
|
virtual const char *getName() const { return "linux/sh386"; }
|
||||||
virtual const int *getFilters() const { return NULL; }
|
virtual const int *getFilters() const { return NULL; }
|
||||||
|
virtual int buildLoader(const Filter *);
|
||||||
|
|
||||||
|
virtual void pack1(OutputFile *fo, Filter &ft);
|
||||||
|
|
||||||
virtual bool canPack();
|
virtual bool canPack();
|
||||||
virtual void pack(OutputFile *fo);
|
|
||||||
// virtual void unpack(OutputFile *fo) { super::unpack(fo); }
|
// virtual void unpack(OutputFile *fo) { super::unpack(fo); }
|
||||||
virtual bool canUnpackVersion(int version) const
|
virtual bool canUnpackVersion(int version) const
|
||||||
{ return (version >= 11); }
|
{ return (version >= 11); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual const upx_byte *getLoader() const;
|
|
||||||
virtual int getLoaderSize() const;
|
|
||||||
virtual bool getShellName(char *buf);
|
virtual bool getShellName(char *buf);
|
||||||
|
|
||||||
virtual void patchLoader();
|
virtual void patchLoader();
|
||||||
|
|
||||||
Elf_LE32_Ehdr *ehdri; // from input file
|
|
||||||
|
|
||||||
int o_shname; // offset to name_of_shell
|
int o_shname; // offset to name_of_shell
|
||||||
int l_shname; // length of name_of_shell
|
int l_shname; // length of name_of_shell
|
||||||
};
|
};
|
||||||
|
|||||||
+373
@@ -0,0 +1,373 @@
|
|||||||
|
/* p_ps1.cpp --
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
|
Copyright (C) 2002 Jens Medoch
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
|
|
||||||
|
Jens Medoch
|
||||||
|
<jssg@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "conf.h"
|
||||||
|
#include "file.h"
|
||||||
|
#include "filter.h"
|
||||||
|
#include "packer.h"
|
||||||
|
#include "p_ps1.h"
|
||||||
|
|
||||||
|
static const
|
||||||
|
#include "stub/l_ps1.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define MIPS_HI(a) (((a) >> 16) /* + (((a)&0x8000)>>15) */ )
|
||||||
|
#define MIPS_LO(a) ((a) & 0xffff)
|
||||||
|
#define MIPS_JP(a) ((0x08 << 24) | (((a) & 0x0fffffff) >> 2))
|
||||||
|
#define CHK_ALIGNED(a,b) ((b) - ((a) % (b)))
|
||||||
|
#define NOCACHE(a) ((a) & 0x1FFFFFFF)
|
||||||
|
|
||||||
|
#define PS_HDR_SIZE 2048 // one CD sector in bytes
|
||||||
|
#define PS_MAX_SIZE 0x1e8000
|
||||||
|
|
||||||
|
#define IH_BKUP (10 * sizeof(LE32))
|
||||||
|
#define EIGHTBIT
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
PackPs1::PackPs1(InputFile *f) :
|
||||||
|
super(f)
|
||||||
|
{
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(ps1_exe_t) == 188);
|
||||||
|
COMPILE_TIME_ASSERT(IH_BKUP == 40);
|
||||||
|
|
||||||
|
overlap = 0;
|
||||||
|
sa_cnt = 0;
|
||||||
|
fdata_size = cfile_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int *PackPs1::getCompressionMethods(int method, int level) const
|
||||||
|
{
|
||||||
|
#ifdef EIGHTBIT
|
||||||
|
return Packer::getDefaultCompressionMethods_8(method, level);
|
||||||
|
#else
|
||||||
|
return Packer::getDefaultCompressionMethods_le32(method, level);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
const int *PackPs1::getFilters() const
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// functions for marker handling
|
||||||
|
int PackPs1::patch_mips_le16(void *b, int blen, const void *old, unsigned new_)
|
||||||
|
{
|
||||||
|
unsigned char w[2];
|
||||||
|
|
||||||
|
set_le16(w, get_be16(old));
|
||||||
|
return patch_le16(b, blen, w, new_);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PackPs1::patch_mips_le32(void *b, int blen, const void *old, unsigned new_)
|
||||||
|
{
|
||||||
|
unsigned char w[4];
|
||||||
|
|
||||||
|
set_le32(w, get_be32(old));
|
||||||
|
return patch_le32(b, blen, w, new_);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PackPs1::patch_hi_lo(void *b, int blen, const void *old_hi, const void *old_lo, unsigned new_)
|
||||||
|
{
|
||||||
|
patch_mips_le16(b, blen, old_lo, MIPS_LO(new_));
|
||||||
|
patch_mips_le16(b, blen, old_hi, MIPS_HI(new_));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
bool PackPs1::canPack()
|
||||||
|
{
|
||||||
|
unsigned char buf[256];
|
||||||
|
fdata_size = file_size-PS_HDR_SIZE;
|
||||||
|
|
||||||
|
fi->seek(0, SEEK_SET);
|
||||||
|
fi->readx(&ih, sizeof(ih));
|
||||||
|
|
||||||
|
if ((memcmp(&ih.id,"PS-X EXE",8) != 0) && (memcmp(&ih.id,"EXE X-SP",8) != 0))
|
||||||
|
return false;
|
||||||
|
fi->readx(buf, sizeof(buf));
|
||||||
|
checkAlreadyPacked(buf, sizeof(buf));
|
||||||
|
if (fdata_size != ih.tx_len || (ih.tx_len & 3))
|
||||||
|
{
|
||||||
|
if (!opt->force)
|
||||||
|
throwCantPack("check header for file size (try --force)");
|
||||||
|
cfile_size = fdata_size;
|
||||||
|
}
|
||||||
|
if (file_size <= (PS_HDR_SIZE*3) && !opt->force)
|
||||||
|
throwCantPack("file is too small (try --force)");
|
||||||
|
if (file_size > PS_MAX_SIZE && !opt->force)
|
||||||
|
throwCantPack("file is too big (try --force)");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
int PackPs1::buildLoader(const Filter *)
|
||||||
|
{
|
||||||
|
initLoader(nrv_loader,sizeof(nrv_loader));
|
||||||
|
addLoader("PSXPREP0","PSXSTSZ0","PSXMAIN0",
|
||||||
|
ih.tx_ptr & 0xffff ? "PSXJSTA0" : "PSXJSTH0",
|
||||||
|
"PSXDECO0",
|
||||||
|
NULL);
|
||||||
|
#ifdef EIGHTBIT
|
||||||
|
if (ph.method == M_NRV2B_8)
|
||||||
|
addLoader("PSXN2BD0", NULL);
|
||||||
|
else if (ph.method == M_NRV2D_8)
|
||||||
|
addLoader("PSXN2DD0", NULL);
|
||||||
|
else if (ph.method == M_NRV2E_8)
|
||||||
|
addLoader("PSXN2ED0", NULL);
|
||||||
|
#else
|
||||||
|
if (ph.method == M_NRV2B_LE32)
|
||||||
|
addLoader("PSXN2BD0", NULL);
|
||||||
|
else if (ph.method == M_NRV2D_LE32)
|
||||||
|
addLoader("PSXN2DD0", NULL);
|
||||||
|
else if (ph.method == M_NRV2E_LE32)
|
||||||
|
addLoader("PSXN2ED0", NULL);
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
throwInternalError("unknown compression method");
|
||||||
|
if (sa_cnt)
|
||||||
|
addLoader((sa_cnt > 0xfffc) ? "MSETBIG0" : "MSETSML0", // set small/big memset
|
||||||
|
(ih.tx_len & 3) ? "MSETUAL0" : "MSETALG0", // un/aligned memset
|
||||||
|
NULL);
|
||||||
|
addLoader("PSXEXIT0", "IDENTSTR", "PSXPHDR0", NULL);
|
||||||
|
return getLoaderSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
void PackPs1::pack(OutputFile *fo)
|
||||||
|
{
|
||||||
|
ibuf.alloc(fdata_size);
|
||||||
|
obuf.allocForCompression(fdata_size);
|
||||||
|
const upx_byte *p_scan = ibuf+(fdata_size-1);
|
||||||
|
|
||||||
|
// read file
|
||||||
|
fi->seek(PS_HDR_SIZE,SEEK_SET);
|
||||||
|
fi->readx(ibuf,fdata_size);
|
||||||
|
|
||||||
|
// this scans the end of file for 2048 bytes sector alignment
|
||||||
|
// this should be padded with zeros
|
||||||
|
while (!(*p_scan--)) { if ((sa_cnt += 1) > (0xfffc<<3)) break; }
|
||||||
|
if (sa_cnt > 0xfffc)
|
||||||
|
sa_cnt = ALIGN_DOWN(sa_cnt,8);
|
||||||
|
else
|
||||||
|
sa_cnt = ALIGN_DOWN(sa_cnt,4);
|
||||||
|
|
||||||
|
// prepare packheader
|
||||||
|
ph.u_len = (fdata_size - sa_cnt);
|
||||||
|
ph.filter = 0;
|
||||||
|
|
||||||
|
Filter ft(ph.level);
|
||||||
|
// compress (max_match = 65535)
|
||||||
|
compressWithFilters(&ft, 512, 0, NULL, 0, 65535);
|
||||||
|
|
||||||
|
if (ph.overlap_overhead <= sa_cnt)
|
||||||
|
overlap = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!opt->force)
|
||||||
|
throwCantPack("packed data overlap (try --force)");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
overlap = ALIGN_UP((ph.overlap_overhead-sa_cnt),4);
|
||||||
|
opt->info_mode += !opt->info_mode ? 1 : 0;
|
||||||
|
infoWarning("%s will load to a %d bytes higher offset",fi->getName(),overlap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&oh, &ih, sizeof(ih));
|
||||||
|
memcpy(&oh.ih_bkup, &ih.epc, IH_BKUP);
|
||||||
|
oh.ih_csum = upx_adler32(&ih.epc, IH_BKUP);
|
||||||
|
|
||||||
|
const int lsize = getLoaderSize();
|
||||||
|
const int h_len = lsize-getLoaderSectionStart("IDENTSTR");
|
||||||
|
const int e_len = lsize-h_len;
|
||||||
|
const int d_len = e_len-getLoaderSectionStart("PSXDECO0");
|
||||||
|
int s_len;
|
||||||
|
getLoaderSection("PSXSTSZ0",&s_len); // get size of pushed/poped regs
|
||||||
|
|
||||||
|
MemBuffer loader(lsize);
|
||||||
|
memcpy(loader,getLoader(),lsize);
|
||||||
|
|
||||||
|
unsigned pad, pad_code;
|
||||||
|
pad = ALIGN_UP((cfile_size ? cfile_size : ih.tx_len), 4);
|
||||||
|
pad_code = CHK_ALIGNED(ph.c_len, 4);
|
||||||
|
|
||||||
|
const unsigned decomp_data_start = NOCACHE(ih.tx_ptr);
|
||||||
|
|
||||||
|
// set the offset for compressed stuff at the very end of file
|
||||||
|
const unsigned comp_data_start = NOCACHE(((decomp_data_start+pad+overlap)-ph.c_len));
|
||||||
|
|
||||||
|
if (!opt->ps1.no_align)
|
||||||
|
// align the packed file to mode 2 data sector size (2048)
|
||||||
|
pad = CHK_ALIGNED(ph.c_len+pad_code+e_len+overlap, 2048);
|
||||||
|
else
|
||||||
|
// no align
|
||||||
|
pad = 0;
|
||||||
|
|
||||||
|
const unsigned entry = NOCACHE(comp_data_start - e_len - pad_code);
|
||||||
|
patchPackHeader(loader,lsize);
|
||||||
|
patch_mips_le32(loader,e_len,"JPEP",MIPS_JP(ih.epc));
|
||||||
|
if (sa_cnt)
|
||||||
|
patch_mips_le16(loader,e_len,"SC",
|
||||||
|
MIPS_LO(sa_cnt > 0xfffc ? sa_cnt >> 3 : sa_cnt));
|
||||||
|
if (ih.tx_ptr & 0xffff)
|
||||||
|
//we have to set the high/low value of the offset
|
||||||
|
patch_hi_lo(loader,e_len,"OH","OL",decomp_data_start);
|
||||||
|
else
|
||||||
|
//only high has to be set, this will save 4 bytes
|
||||||
|
patch_mips_le16(loader,e_len,"OH",decomp_data_start>>16);
|
||||||
|
patch_hi_lo(loader,e_len,"CH","CL",comp_data_start);
|
||||||
|
patch_hi_lo(loader,e_len,"DH","DL",entry+(e_len-d_len));
|
||||||
|
patch_mips_le16(loader,e_len,"LS",d_len+s_len);
|
||||||
|
|
||||||
|
// set the file load address
|
||||||
|
oh.tx_ptr = entry - pad;
|
||||||
|
// set the correct file len in header
|
||||||
|
oh.tx_len = ph.c_len + e_len + pad + pad_code;
|
||||||
|
// set the code entry
|
||||||
|
oh.epc = entry;
|
||||||
|
|
||||||
|
// write loader + compressed file
|
||||||
|
upx_bytep paddata = ibuf;
|
||||||
|
memset(paddata,0,fdata_size);
|
||||||
|
|
||||||
|
fo->write(&oh,sizeof(oh));
|
||||||
|
|
||||||
|
// id & upx header
|
||||||
|
fo->write(loader+e_len,h_len);
|
||||||
|
// align the ps exe header (mode 2 sector data size)
|
||||||
|
fo->write(paddata,PS_HDR_SIZE-fo->getBytesWritten());
|
||||||
|
if (pad)
|
||||||
|
// align the file
|
||||||
|
fo->write(paddata,pad);
|
||||||
|
// entry
|
||||||
|
fo->write(loader,e_len);
|
||||||
|
if (pad_code)
|
||||||
|
// align the mips runtime code
|
||||||
|
fo->write(paddata,pad_code);
|
||||||
|
fo->write(obuf,ph.c_len);
|
||||||
|
|
||||||
|
// verify
|
||||||
|
verifyOverlappingDecompression();
|
||||||
|
|
||||||
|
// finally check the compression ratio
|
||||||
|
if (!checkFinalCompressionRatio(fo))
|
||||||
|
throwNotCompressible();
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
printf("%-13s: compressed : %8ld bytes\n", getName(), (long) ph.c_len);
|
||||||
|
printf("%-13s: decompressor : %8ld bytes\n", getName(), (long) e_len);
|
||||||
|
printf("%-13s: code entry : %08X bytes\n", getName(), (unsigned int) oh.epc);
|
||||||
|
printf("%-13s: load address : %08X bytes\n", getName(), (unsigned int) oh.tx_ptr);
|
||||||
|
printf("%-13s: section size : %8ld bytes\n", getName(), (long) oh.tx_len);
|
||||||
|
printf("%-13s: eof in mem IF: %08X bytes\n", getName(), (unsigned int) ih.tx_ptr+ih.tx_len);
|
||||||
|
printf("%-13s: eof in mem OF: %08X bytes\n", getName(), (unsigned int) oh.tx_ptr+oh.tx_len);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
int PackPs1::canUnpack()
|
||||||
|
{
|
||||||
|
if (!readPackHeader(0x400))
|
||||||
|
return false;
|
||||||
|
if (file_size <= (off_t) ph.c_len)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
void PackPs1::unpack(OutputFile *fo)
|
||||||
|
{
|
||||||
|
fdata_size = file_size-PS_HDR_SIZE;
|
||||||
|
ibuf.alloc(file_size);
|
||||||
|
|
||||||
|
fi->seek(0x0,SEEK_SET);
|
||||||
|
fi->readx(&ih,sizeof(ih));
|
||||||
|
fi->seek(PS_HDR_SIZE,SEEK_SET);
|
||||||
|
fi->readx(ibuf,fdata_size);
|
||||||
|
|
||||||
|
// test & restore orig exec hdr
|
||||||
|
if (ih.ih_csum != upx_adler32(&ih.ih_bkup,IH_BKUP))
|
||||||
|
throwCantUnpack("file is possibly modified/hacked/protected; take care!");
|
||||||
|
|
||||||
|
memcpy(&oh, &ih, sizeof(ih));
|
||||||
|
memcpy(&oh.epc, &ih.ih_bkup, IH_BKUP);
|
||||||
|
|
||||||
|
// clear backup and checksum of header
|
||||||
|
memset(&oh.ih_bkup,0,IH_BKUP+4);
|
||||||
|
|
||||||
|
// check for removed sector alignment
|
||||||
|
const unsigned pad = oh.tx_len - ph.u_len;
|
||||||
|
|
||||||
|
obuf.allocForUncompression(ph.u_len+pad);
|
||||||
|
memset(obuf,0,obuf.getSize());
|
||||||
|
|
||||||
|
// decompress
|
||||||
|
decompress(ibuf+(fdata_size-ph.c_len),obuf);
|
||||||
|
|
||||||
|
// write decompressed file
|
||||||
|
if (fo)
|
||||||
|
{
|
||||||
|
fo->write(&oh,sizeof(oh));
|
||||||
|
memset(ibuf,0,fdata_size);
|
||||||
|
fo->write(ibuf,PS_HDR_SIZE-fo->getBytesWritten());
|
||||||
|
fo->write(obuf,ph.u_len+pad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
vi:ts=4:et:nowrap
|
||||||
|
*/
|
||||||
|
|
||||||
+112
@@ -0,0 +1,112 @@
|
|||||||
|
/* p_ps1.h --
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
|
Copyright (C) 2002 Jens Medoch
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
|
|
||||||
|
Jens Medoch
|
||||||
|
<jssg@users.sourceforge.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __UPX_P_PS1_H
|
||||||
|
#define __UPX_P_PS1_H
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// ps1/exe
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
class PackPs1 : public Packer
|
||||||
|
{
|
||||||
|
typedef Packer super;
|
||||||
|
public:
|
||||||
|
PackPs1(InputFile *f);
|
||||||
|
virtual int getVersion() const { return 13; }
|
||||||
|
virtual int getFormat() const { return UPX_F_PS1_EXE; }
|
||||||
|
virtual const char *getName() const { return "ps1/exe"; }
|
||||||
|
virtual const int *getCompressionMethods(int method, int level) const;
|
||||||
|
virtual const int *getFilters() const;
|
||||||
|
|
||||||
|
virtual void pack(OutputFile *fo);
|
||||||
|
virtual void unpack(OutputFile *fo);
|
||||||
|
|
||||||
|
virtual bool canPack();
|
||||||
|
virtual int canUnpack();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual int buildLoader(const Filter *ft);
|
||||||
|
virtual int patch_mips_le16(void *b, int blen, const void *old, unsigned new_);
|
||||||
|
virtual int patch_mips_le32(void *b, int blen, const void *old, unsigned new_);
|
||||||
|
virtual int patch_hi_lo(void *b, int blen, const void *old_hi, const void *old_lo, unsigned new_);
|
||||||
|
|
||||||
|
struct ps1_exe_t
|
||||||
|
{
|
||||||
|
char id[8];
|
||||||
|
LE32 text;
|
||||||
|
LE32 data;
|
||||||
|
LE32 epc;
|
||||||
|
LE32 gp;
|
||||||
|
LE32 tx_ptr;
|
||||||
|
LE32 tx_len;
|
||||||
|
LE32 da_ptr;
|
||||||
|
LE32 da_len;
|
||||||
|
LE32 bs_ptr;
|
||||||
|
LE32 bs_len;
|
||||||
|
LE32 sd_ptr;
|
||||||
|
LE32 sd_len;
|
||||||
|
LE32 sp,fp,gp0,ra,k0;
|
||||||
|
char origin[60];
|
||||||
|
// some safety space after that
|
||||||
|
char pad[8];
|
||||||
|
// i'll place the backup of the original
|
||||||
|
// execution file structure here (epc - sd_len)
|
||||||
|
LE32 ih_bkup[10];
|
||||||
|
// plus checksum for the backup
|
||||||
|
LE32 ih_csum;
|
||||||
|
// here will find the id & the upx header it's place.
|
||||||
|
// btw only the 'epc - sd_len' entries init the executable.
|
||||||
|
// so stuff placed here will not load and waste memory.
|
||||||
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
|
ps1_exe_t ih, oh;
|
||||||
|
|
||||||
|
upx_uint overlap;
|
||||||
|
upx_uint sa_cnt;
|
||||||
|
|
||||||
|
// filesize-PS_HDR_SIZE
|
||||||
|
upx_uint fdata_size;
|
||||||
|
// calculated filesize
|
||||||
|
upx_uint cfile_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* already included */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
vi:ts=4:et
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
+17
-15
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -45,13 +45,12 @@ bool PackSys::canPack()
|
|||||||
{
|
{
|
||||||
unsigned char buf[128];
|
unsigned char buf[128];
|
||||||
|
|
||||||
fi->readx(buf,128);
|
fi->readx(buf, sizeof(buf));
|
||||||
if (memcmp (buf,"\xff\xff\xff\xff",4) != 0)
|
if (memcmp (buf,"\xff\xff\xff\xff",4) != 0)
|
||||||
return false;
|
return false;
|
||||||
if (!fn_has_ext(fi->getName(),"sys"))
|
if (!fn_has_ext(fi->getName(),"sys"))
|
||||||
return false;
|
return false;
|
||||||
if (find_le32(buf,128,UPX_MAGIC_LE32) >= 0)
|
checkAlreadyPacked(buf, sizeof(buf));
|
||||||
throwAlreadyPacked();
|
|
||||||
if (file_size < 1024)
|
if (file_size < 1024)
|
||||||
throwCantPack("file is too small");
|
throwCantPack("file is too small");
|
||||||
if (file_size > 0x10000)
|
if (file_size > 0x10000)
|
||||||
@@ -66,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");
|
||||||
@@ -74,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)
|
||||||
@@ -91,8 +90,8 @@ 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[getLoaderSectionStart("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);
|
||||||
|
|
||||||
@@ -105,19 +104,22 @@ void PackSys::patchLoader(OutputFile *fo,
|
|||||||
|
|
||||||
int PackSys::buildLoader(const Filter *ft)
|
int PackSys::buildLoader(const Filter *ft)
|
||||||
{
|
{
|
||||||
const int filter_id = ft->id;
|
|
||||||
initLoader(nrv2b_loader,sizeof(nrv2b_loader));
|
initLoader(nrv2b_loader,sizeof(nrv2b_loader));
|
||||||
addLoader("SYSMAIN1",
|
addLoader("SYSMAIN1",
|
||||||
opt->cpu == opt->CPU_8086 ? "SYSI0861" : "SYSI2861",
|
opt->cpu == opt->CPU_8086 ? "SYSI0861" : "SYSI2861",
|
||||||
"SYSMAIN2""SYSSUBSI",
|
"SYSMAIN2""SYSSUBSI",
|
||||||
filter_id ? "SYSCALLT" : "",
|
ph.first_offset_found == 1 ? "SYSSBBBP" : "",
|
||||||
|
ft->id ? "SYSCALLT" : "",
|
||||||
"SYSMAIN3""UPX1HEAD""SYSCUTPO""NRV2B160""NRVDDONE""NRVDECO1",
|
"SYSMAIN3""UPX1HEAD""SYSCUTPO""NRV2B160""NRVDDONE""NRVDECO1",
|
||||||
ph.max_offset_found <= 0xd00 ? "NRVLED00" : "NRVGTD00",
|
ph.max_offset_found <= 0xd00 ? "NRVLED00" : "NRVGTD00",
|
||||||
"NRVDECO2""NRV2B169",
|
"NRVDECO2""NRV2B169",
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
if (filter_id)
|
if (ft->id)
|
||||||
addFilter16(filter_id);
|
{
|
||||||
|
assert(ft->calls > 0);
|
||||||
|
addFilter16(ft->id);
|
||||||
|
}
|
||||||
addLoader("SYSMAIN5",
|
addLoader("SYSMAIN5",
|
||||||
opt->cpu == opt->CPU_8086 ? "SYSI0862" : "SYSI2862",
|
opt->cpu == opt->CPU_8086 ? "SYSI0862" : "SYSI2862",
|
||||||
"SYSJUMP1",
|
"SYSJUMP1",
|
||||||
|
|||||||
+5
-5
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ class PackSys : public PackCom
|
|||||||
typedef PackCom super;
|
typedef PackCom super;
|
||||||
public:
|
public:
|
||||||
PackSys(InputFile *f) : super(f) { }
|
PackSys(InputFile *f) : super(f) { }
|
||||||
virtual int getVersion() const { return 11; }
|
virtual int getVersion() const { return 13; }
|
||||||
virtual int getFormat() const { return UPX_F_DOS_SYS; }
|
virtual int getFormat() const { return UPX_F_DOS_SYS; }
|
||||||
virtual const char *getName() const { return "dos/sys"; }
|
virtual const char *getName() const { return "dos/sys"; }
|
||||||
|
|
||||||
@@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+80
-63
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,9 +22,10 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
@@ -41,32 +42,72 @@ static const
|
|||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
int PackTmt::getCompressionMethod() const
|
PackTmt::PackTmt(InputFile *f) : super(f)
|
||||||
{
|
{
|
||||||
if (M_IS_NRV2B(opt->method))
|
COMPILE_TIME_ASSERT(sizeof(tmt_header_t) == 44);
|
||||||
return M_NRV2B_LE32;
|
}
|
||||||
if (M_IS_NRV2D(opt->method))
|
|
||||||
return M_NRV2D_LE32;
|
|
||||||
return opt->level > 1 && file_size >= 512*1024 ? M_NRV2D_LE32 : M_NRV2B_LE32;
|
const int *PackTmt::getCompressionMethods(int method, int level) const
|
||||||
|
{
|
||||||
|
return Packer::getDefaultCompressionMethods_le32(method, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const int *PackTmt::getFilters() const
|
const int *PackTmt::getFilters() const
|
||||||
{
|
{
|
||||||
static const int filters[] = { 0x26, 0x24, 0x11, 0x14, 0x13, 0x16,
|
static const int filters[] = {
|
||||||
0x25, 0x12, 0x15, -1 };
|
0x26, 0x24, 0x11, 0x14, 0x13, 0x16, 0x25, 0x12, 0x15,
|
||||||
|
-1 };
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
initLoader(nrv_loader,sizeof(nrv_loader));
|
||||||
|
addLoader("IDENTSTR""TMTMAIN1",
|
||||||
|
ft->id ? "TMTCALT1" : "",
|
||||||
|
"TMTMAIN2""UPX1HEAD""TMTCUTPO""+0XXXXXX",
|
||||||
|
getDecompressor(),
|
||||||
|
"TMTMAIN5",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
if (ft->id)
|
||||||
|
{
|
||||||
|
assert(ft->calls > 0);
|
||||||
|
addLoader("TMTCALT2",NULL);
|
||||||
|
addFilter32(ft->id);
|
||||||
|
}
|
||||||
|
addLoader("TMTRELOC""RELOC320",
|
||||||
|
big_relocs ? "REL32BIG" : "",
|
||||||
|
"RELOC32J""TMTJUMP1",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
return getLoaderSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// 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))
|
||||||
unsigned char h[0x40];
|
unsigned char h[0x40];
|
||||||
int ic;
|
int ic;
|
||||||
unsigned exe_offset = 0;
|
unsigned exe_offset = 0;
|
||||||
@@ -111,14 +152,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
|
||||||
}
|
}
|
||||||
@@ -126,7 +169,9 @@ bool PackTmt::readFileHeader()
|
|||||||
|
|
||||||
bool PackTmt::canPack()
|
bool PackTmt::canPack()
|
||||||
{
|
{
|
||||||
return readFileHeader();
|
if (!readFileHeader())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -136,6 +181,8 @@ bool PackTmt::canPack()
|
|||||||
|
|
||||||
void PackTmt::pack(OutputFile *fo)
|
void PackTmt::pack(OutputFile *fo)
|
||||||
{
|
{
|
||||||
|
big_relocs = 0;
|
||||||
|
|
||||||
Packer::handleStub(fi,fo,adam_offset);
|
Packer::handleStub(fi,fo,adam_offset);
|
||||||
|
|
||||||
const unsigned usize = ih.imagesize;
|
const unsigned usize = ih.imagesize;
|
||||||
@@ -160,18 +207,13 @@ void PackTmt::pack(OutputFile *fo)
|
|||||||
checkOverlay(overlay);
|
checkOverlay(overlay);
|
||||||
|
|
||||||
unsigned relocsize = 0;
|
unsigned relocsize = 0;
|
||||||
int big;
|
|
||||||
//if (rsize)
|
//if (rsize)
|
||||||
{
|
{
|
||||||
for (unsigned ic=4; ic<=rsize; ic+=4)
|
for (unsigned ic=4; ic<=rsize; ic+=4)
|
||||||
set_le32(wrkmem+ic,get_le32(wrkmem+ic)-4);
|
set_le32(wrkmem+ic,get_le32(wrkmem+ic)-4);
|
||||||
relocsize = optimizeReloc32(wrkmem+4,rsize/4,wrkmem,ibuf,1,&big)-wrkmem;
|
relocsize = ptr_diff(optimizeReloc32(wrkmem+4,rsize/4,wrkmem,ibuf,1,&big_relocs), wrkmem);
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter
|
|
||||||
Filter ft(opt->level);
|
|
||||||
tryFilters(&ft, ibuf, usize);
|
|
||||||
|
|
||||||
wrkmem[relocsize++] = 0;
|
wrkmem[relocsize++] = 0;
|
||||||
set_le32(wrkmem+relocsize,ih.entry); // save original entry point
|
set_le32(wrkmem+relocsize,ih.entry); // save original entry point
|
||||||
relocsize += 4;
|
relocsize += 4;
|
||||||
@@ -179,38 +221,13 @@ void PackTmt::pack(OutputFile *fo)
|
|||||||
relocsize += 4;
|
relocsize += 4;
|
||||||
memcpy(ibuf+usize,wrkmem,relocsize);
|
memcpy(ibuf+usize,wrkmem,relocsize);
|
||||||
|
|
||||||
ph.filter = ft.id;
|
// prepare packheader
|
||||||
ph.filter_cto = ft.cto;
|
|
||||||
ph.u_len = usize + relocsize;
|
ph.u_len = usize + relocsize;
|
||||||
if (!compress(ibuf,obuf))
|
// prepare filter
|
||||||
throwNotCompressible();
|
Filter ft(ph.level);
|
||||||
// make sure the decompressor will be paragraph aligned
|
ft.buf_len = usize;
|
||||||
const unsigned overlapoh = ((findOverlapOverhead(obuf,512)+0x20)
|
// compress
|
||||||
&~ 0xf) - (ph.u_len & 0xf);
|
compressWithFilters(&ft, 512);
|
||||||
|
|
||||||
// verify filter
|
|
||||||
ft.verifyUnfilter();
|
|
||||||
|
|
||||||
// prepare loader
|
|
||||||
initLoader(nrv_loader,sizeof(nrv_loader));
|
|
||||||
addLoader("IDENTSTR""TMTMAIN1",
|
|
||||||
ft.id ? "TMTCALT1" : "",
|
|
||||||
"TMTMAIN2""UPX1HEAD""TMTCUTPO""+0XXXXXX",
|
|
||||||
getDecompressor(),
|
|
||||||
"TMTMAIN5",
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
if (ft.id)
|
|
||||||
{
|
|
||||||
assert(ft.calls > 0);
|
|
||||||
addLoader("TMTCALT2",NULL);
|
|
||||||
addFilter32(ft.id);
|
|
||||||
}
|
|
||||||
addLoader("TMTRELOC""RELOC320",
|
|
||||||
big ? "REL32BIG" : "",
|
|
||||||
"RELOC32J""TMTJUMP1",
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
const unsigned lsize = getLoaderSize();
|
const unsigned lsize = getLoaderSize();
|
||||||
MemBuffer loader(lsize);
|
MemBuffer loader(lsize);
|
||||||
@@ -222,18 +239,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
|
||||||
@@ -250,7 +267,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();
|
||||||
|
|
||||||
// copy the overlay
|
// copy the overlay
|
||||||
copyOverlay(fo, overlay, &obuf);
|
copyOverlay(fo, overlay, &obuf);
|
||||||
@@ -263,7 +280,7 @@ void PackTmt::pack(OutputFile *fo)
|
|||||||
|
|
||||||
int PackTmt::canUnpack()
|
int PackTmt::canUnpack()
|
||||||
{
|
{
|
||||||
if (!PackTmt::readFileHeader())
|
if (!readFileHeader())
|
||||||
return false;
|
return false;
|
||||||
fi->seek(adam_offset, SEEK_SET);
|
fi->seek(adam_offset, SEEK_SET);
|
||||||
return readPackHeader(512) ? 1 : -1;
|
return readPackHeader(512) ? 1 : -1;
|
||||||
@@ -294,7 +311,7 @@ void PackTmt::unpack(OutputFile *fo)
|
|||||||
Filter ft(ph.level);
|
Filter ft(ph.level);
|
||||||
ft.init(ph.filter, 0);
|
ft.init(ph.filter, 0);
|
||||||
ft.cto = (unsigned char) (ph.version < 11 ? (get_le32(obuf+ph.u_len-12) >> 24) : ph.filter_cto);
|
ft.cto = (unsigned char) (ph.version < 11 ? (get_le32(obuf+ph.u_len-12) >> 24) : ph.filter_cto);
|
||||||
ft.unfilter(obuf, relocs-obuf);
|
ft.unfilter(obuf, ptr_diff(relocs, obuf));
|
||||||
}
|
}
|
||||||
|
|
||||||
// decode relocations
|
// decode relocations
|
||||||
|
|||||||
+13
-7
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -38,11 +38,11 @@ class PackTmt : public Packer
|
|||||||
{
|
{
|
||||||
typedef Packer super;
|
typedef Packer super;
|
||||||
public:
|
public:
|
||||||
PackTmt(InputFile *f) : super(f) { assert(sizeof(tmt_header_t) == 44); }
|
PackTmt(InputFile *f);
|
||||||
virtual int getVersion() const { return 11; }
|
virtual int getVersion() const { return 13; }
|
||||||
virtual int getFormat() const { return UPX_F_TMT_ADAM; }
|
virtual int getFormat() const { return UPX_F_TMT_ADAM; }
|
||||||
virtual const char *getName() const { return "tmt/adam"; }
|
virtual const char *getName() const { return "tmt/adam"; }
|
||||||
virtual int getCompressionMethod() const;
|
virtual const int *getCompressionMethods(int method, int level) const;
|
||||||
virtual const int *getFilters() const;
|
virtual const int *getFilters() const;
|
||||||
|
|
||||||
virtual void pack(OutputFile *fo);
|
virtual void pack(OutputFile *fo);
|
||||||
@@ -52,9 +52,15 @@ public:
|
|||||||
virtual int canUnpack();
|
virtual int canUnpack();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
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);
|
||||||
|
|
||||||
unsigned adam_offset;
|
unsigned adam_offset;
|
||||||
|
int big_relocs;
|
||||||
|
|
||||||
struct tmt_header_t
|
struct tmt_header_t
|
||||||
{
|
{
|
||||||
|
|||||||
+131
-60
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,13 +22,14 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
#include "filter.h"
|
||||||
#include "packer.h"
|
#include "packer.h"
|
||||||
#include "p_tos.h"
|
#include "p_tos.h"
|
||||||
|
|
||||||
@@ -40,6 +41,10 @@ static const
|
|||||||
#include "stub/l_t_n2d.h"
|
#include "stub/l_t_n2d.h"
|
||||||
static const
|
static const
|
||||||
#include "stub/l_t_n2ds.h"
|
#include "stub/l_t_n2ds.h"
|
||||||
|
static const
|
||||||
|
#include "stub/l_t_n2e.h"
|
||||||
|
static const
|
||||||
|
#include "stub/l_t_n2es.h"
|
||||||
|
|
||||||
// #define TESTING
|
// #define TESTING
|
||||||
|
|
||||||
@@ -53,17 +58,14 @@ static const
|
|||||||
PackTos::PackTos(InputFile *f) :
|
PackTos::PackTos(InputFile *f) :
|
||||||
super(f)
|
super(f)
|
||||||
{
|
{
|
||||||
assert(FH_SIZE == 28);
|
COMPILE_TIME_ASSERT(FH_SIZE == 28);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int PackTos::getCompressionMethod() const
|
const int *PackTos::getCompressionMethods(int method, int level) const
|
||||||
{
|
{
|
||||||
if (M_IS_NRV2B(opt->method))
|
bool small = ih.fh_text + ih.fh_data <= 256*1024;
|
||||||
return M_NRV2B_8;
|
return Packer::getDefaultCompressionMethods_8(method, level, small);
|
||||||
if (M_IS_NRV2D(opt->method))
|
|
||||||
return M_NRV2D_8;
|
|
||||||
return opt->level > 1 && file_size >= 512*1024 ? M_NRV2D_8 : M_NRV2B_8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -75,20 +77,24 @@ const int *PackTos::getFilters() const
|
|||||||
|
|
||||||
const upx_byte *PackTos::getLoader() const
|
const upx_byte *PackTos::getLoader() const
|
||||||
{
|
{
|
||||||
if (M_IS_NRV2B(opt->method))
|
if (M_IS_NRV2B(ph.method))
|
||||||
return opt->small ? nrv2b_loader_small : nrv2b_loader;
|
return opt->small ? nrv2b_loader_small : nrv2b_loader;
|
||||||
if (M_IS_NRV2D(opt->method))
|
if (M_IS_NRV2D(ph.method))
|
||||||
return opt->small ? nrv2d_loader_small : nrv2d_loader;
|
return opt->small ? nrv2d_loader_small : nrv2d_loader;
|
||||||
|
if (M_IS_NRV2E(ph.method))
|
||||||
|
return opt->small ? nrv2e_loader_small : nrv2e_loader;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int PackTos::getLoaderSize() const
|
int PackTos::getLoaderSize() const
|
||||||
{
|
{
|
||||||
if (M_IS_NRV2B(opt->method))
|
if (M_IS_NRV2B(ph.method))
|
||||||
return opt->small ? sizeof(nrv2b_loader_small) : sizeof(nrv2b_loader);
|
return opt->small ? sizeof(nrv2b_loader_small) : sizeof(nrv2b_loader);
|
||||||
if (M_IS_NRV2D(opt->method))
|
if (M_IS_NRV2D(ph.method))
|
||||||
return opt->small ? sizeof(nrv2d_loader_small) : sizeof(nrv2d_loader);
|
return opt->small ? sizeof(nrv2d_loader_small) : sizeof(nrv2d_loader);
|
||||||
|
if (M_IS_NRV2E(ph.method))
|
||||||
|
return opt->small ? sizeof(nrv2e_loader_small) : sizeof(nrv2e_loader);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,15 +138,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -176,65 +182,118 @@ bool PackTos::checkFileHeader()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// some 68000 opcodes for patching
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
enum m68k_reg_t {
|
||||||
|
REG_D0, REG_D1, REG_D2, REG_D3, REG_D4, REG_D5, REG_D6, REG_D7,
|
||||||
|
REG_A0, REG_A1, REG_A2, REG_A3, REG_A4, REG_A5, REG_A6, REG_A7
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned OP_DBRA(int d_reg)
|
||||||
|
{
|
||||||
|
assert(d_reg >= REG_D0 && d_reg <= REG_D7);
|
||||||
|
return 0x51c8 | (d_reg & 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned OP_JMP(int a_reg)
|
||||||
|
{
|
||||||
|
// jmp (a0)
|
||||||
|
assert(a_reg >= REG_A0 && a_reg <= REG_A7);
|
||||||
|
return 0x4ed0 | (a_reg & 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned OP_MOVEI_L(int d_reg)
|
||||||
|
{
|
||||||
|
// movei.l #XXXXXXXX,d0
|
||||||
|
assert(d_reg >= REG_D0 && d_reg <= REG_D7);
|
||||||
|
return 0x203c | ((d_reg & 7) << 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned OP_MOVEQ(int value, int d_reg)
|
||||||
|
{
|
||||||
|
// moveq.l #0,d0
|
||||||
|
assert(d_reg >= REG_D0 && d_reg <= REG_D7);
|
||||||
|
assert(value >= -128 && value <= 127);
|
||||||
|
return 0x7000 | ((d_reg & 7) << 9) | (value & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned OP_SUBQ_L(int value, int d_reg)
|
||||||
|
{
|
||||||
|
assert(value >= 1 && value <= 8);
|
||||||
|
assert(d_reg >= REG_D0 && d_reg <= REG_D7);
|
||||||
|
return 0x5180 | ((value & 7) << 9) | (d_reg & 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned OP_SUBQ_W(int value, int d_reg)
|
||||||
|
{
|
||||||
|
assert(value >= 1 && value <= 8);
|
||||||
|
assert(d_reg >= REG_D0 && d_reg <= REG_D7);
|
||||||
|
return 0x5140 | ((value & 7) << 9) | (d_reg & 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
unsigned PackTos::patch_d0_subq(void *b, int blen, unsigned d0,
|
unsigned PackTos::patch_d_subq(void *b, int blen,
|
||||||
|
int d_reg, unsigned d_value,
|
||||||
const char *subq_marker)
|
const char *subq_marker)
|
||||||
{
|
{
|
||||||
// patch a "subq.l #1,d0" or "subq.w #1,d0".
|
// patch a "subq.l #1,d0" or "subq.w #1,d0".
|
||||||
// also convert into "dbra" if possible
|
// also convert into "dbra" if possible
|
||||||
assert((int)d0 > 0);
|
assert(d_reg >= REG_D0 && d_reg <= REG_D7);
|
||||||
|
assert((int)d_value > 0);
|
||||||
|
|
||||||
int boff = find_be16(b, blen, get_be16(subq_marker));
|
int boff = find_be16(b, blen, get_be16(subq_marker));
|
||||||
if (boff < 0)
|
if (boff < 0)
|
||||||
throwBadLoader();
|
throwBadLoader();
|
||||||
|
|
||||||
unsigned char *p = (unsigned char *)b + boff;
|
upx_byte *p = (upx_byte *)b + boff;
|
||||||
if (p[2] == 0x66) // bne.b XXX
|
if (p[2] == 0x66) // bne.b XXX
|
||||||
checkPatch(b, blen, boff, 4);
|
checkPatch(b, blen, boff, 4);
|
||||||
else
|
else
|
||||||
checkPatch(b, blen, boff, 2);
|
checkPatch(b, blen, boff, 2);
|
||||||
|
|
||||||
if (d0 > 65536)
|
if (d_value > 65536)
|
||||||
{
|
{
|
||||||
set_be16(p, 0x5380); // subq.l #1,d0
|
set_be16(p, OP_SUBQ_L(1, d_reg)); // subq.l #1,d0
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (p[2] == 0x66) // bne.b XXX
|
if (p[2] == 0x66) // bne.b XXX
|
||||||
{
|
{
|
||||||
set_be16(p, 0x51c8); // dbra d0,XXX
|
set_be16(p, OP_DBRA(d_reg)); // dbra d0,XXX
|
||||||
// adjust and extend branch from 8 to 16 bits
|
// adjust and extend branch from 8 to 16 bits
|
||||||
int branch = (signed char) p[3];
|
int branch = (signed char) p[3];
|
||||||
set_be16(p+2, branch+2);
|
set_be16(p+2, branch+2);
|
||||||
// adjust d0
|
// adjust d0
|
||||||
d0 -= 1;
|
d_value -= 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
set_be16(p, 0x5340); // subq.w #1,d0
|
set_be16(p, OP_SUBQ_W(1, d_reg)); // subq.w #1,d0
|
||||||
}
|
}
|
||||||
d0 &= 0xffff;
|
d_value &= 0xffff;
|
||||||
}
|
}
|
||||||
return d0;
|
return d_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned PackTos::patch_d0_loop(void *b, int blen, unsigned d0,
|
unsigned PackTos::patch_d_loop(void *b, int blen,
|
||||||
const char *d0_marker, const char *subq_marker)
|
int d_reg, unsigned d_value,
|
||||||
|
const char *d_marker, const char *subq_marker)
|
||||||
{
|
{
|
||||||
d0 = patch_d0_subq(b, blen, d0, subq_marker);
|
d_value = patch_d_subq(b, blen, d_reg, d_value, subq_marker);
|
||||||
|
|
||||||
int boff = find_be32(b, blen, get_be32(d0_marker));
|
int boff = find_be32(b, blen, get_be32(d_marker));
|
||||||
checkPatch(b, blen, boff, 4);
|
checkPatch(b, blen, boff, 4);
|
||||||
|
upx_byte *p = (upx_byte *)b + boff;
|
||||||
unsigned char *p = (unsigned char *)b + boff;
|
assert(get_be16(p - 2) == OP_MOVEI_L(d_reg)); // move.l #XXXXXXXX,d0
|
||||||
assert(get_be16(p - 2) == 0x203c); // move.l #XXXXXXXX,d0
|
set_be32(p, d_value);
|
||||||
set_be32(p, d0);
|
return d_value;
|
||||||
|
|
||||||
return d0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -262,7 +321,7 @@ static int check_relocs(const upx_byte *relocs, unsigned rsize, unsigned isize,
|
|||||||
return -1;
|
return -1;
|
||||||
if (i >= rsize) // premature EOF in relocs
|
if (i >= rsize) // premature EOF in relocs
|
||||||
return -1;
|
return -1;
|
||||||
int c = relocs[i++];
|
unsigned c = relocs[i++];
|
||||||
if (c == 0) // end marker
|
if (c == 0) // end marker
|
||||||
break;
|
break;
|
||||||
else if (c == 1) // increase fixup, no reloc
|
else if (c == 1) // increase fixup, no reloc
|
||||||
@@ -291,13 +350,24 @@ static int check_relocs(const upx_byte *relocs, unsigned rsize, unsigned isize,
|
|||||||
|
|
||||||
bool PackTos::canPack()
|
bool PackTos::canPack()
|
||||||
{
|
{
|
||||||
|
#if 0 // debug
|
||||||
|
# define p(x) printf("%-30s 0x%04x\n", #x, x)
|
||||||
|
p(OP_DBRA(REG_D0));
|
||||||
|
p(OP_MOVEI_L(REG_D0));
|
||||||
|
p(OP_MOVEQ(-1, REG_D0));
|
||||||
|
p(OP_MOVEQ(1, REG_D2));
|
||||||
|
p(OP_MOVEQ(1, REG_D3));
|
||||||
|
p(OP_SUBQ_W(1, REG_D0));
|
||||||
|
p(OP_SUBQ_L(1, REG_D0));
|
||||||
|
# undef p
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!readFileHeader())
|
if (!readFileHeader())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
unsigned char buf[512];
|
unsigned char buf[512];
|
||||||
fi->readx(buf, sizeof(buf));
|
fi->readx(buf, sizeof(buf));
|
||||||
if (find_le32(buf,sizeof(buf),UPX_MAGIC_LE32) >= 0)
|
checkAlreadyPacked(buf, sizeof(buf));
|
||||||
throwAlreadyPacked();
|
|
||||||
|
|
||||||
if (!checkFileHeader())
|
if (!checkFileHeader())
|
||||||
throwCantPack("unsupported header flags");
|
throwCantPack("unsupported header flags");
|
||||||
@@ -360,7 +430,7 @@ void PackTos::pack(OutputFile *fo)
|
|||||||
printf("xx1 reloc: %d, overlay: %d, fixup: %d\n", relocsize, overlay, overlay >= 4 ? (int)get_be32(ibuf+t) : -1);
|
printf("xx1 reloc: %d, overlay: %d, fixup: %d\n", relocsize, overlay, overlay >= 4 ? (int)get_be32(ibuf+t) : -1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Check relocs (see load_and_reloc() in mint/src/mem.c).
|
// Check relocs (see load_and_reloc() in freemint/sys/memory.c).
|
||||||
// Must work around TOS bugs and lots of broken programs.
|
// Must work around TOS bugs and lots of broken programs.
|
||||||
int r = 0;
|
int r = 0;
|
||||||
if (overlay < 4)
|
if (overlay < 4)
|
||||||
@@ -407,14 +477,15 @@ void PackTos::pack(OutputFile *fo)
|
|||||||
// alloc buffer
|
// alloc buffer
|
||||||
obuf.allocForCompression(t + d_len + 512);
|
obuf.allocForCompression(t + d_len + 512);
|
||||||
|
|
||||||
// compress (max_match = 65535)
|
// prepare packheader
|
||||||
ph.u_len = t;
|
ph.u_len = t;
|
||||||
if (!compress(ibuf,obuf,0,65535))
|
// prepare filter
|
||||||
throwNotCompressible();
|
Filter ft(ph.level);
|
||||||
|
// compress (max_match = 65535)
|
||||||
|
compressWithFilters(&ft, 512, 0, NULL, 0, 65535);
|
||||||
|
|
||||||
// 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);
|
unsigned offset = (ph.u_len + ph.overlap_overhead) - ph.c_len;
|
||||||
unsigned offset = (ph.u_len + overlapoh) - ph.c_len;
|
|
||||||
|
|
||||||
// compute addresses
|
// compute addresses
|
||||||
unsigned o_text, o_data, o_bss;
|
unsigned o_text, o_data, o_bss;
|
||||||
@@ -456,8 +527,8 @@ void PackTos::pack(OutputFile *fo)
|
|||||||
while (dirty_bss & (dirty_bss_align - 1))
|
while (dirty_bss & (dirty_bss_align - 1))
|
||||||
dirty_bss++;
|
dirty_bss++;
|
||||||
// adjust bss, assert room for some stack
|
// adjust bss, assert room for some stack
|
||||||
if (dirty_bss + 256 > o_bss)
|
if (dirty_bss + 512 > o_bss)
|
||||||
o_bss = dirty_bss + 256;
|
o_bss = dirty_bss + 512;
|
||||||
|
|
||||||
// dword align the len of the final bss segment
|
// dword align the len of the final bss segment
|
||||||
while (o_bss & 3)
|
while (o_bss & 3)
|
||||||
@@ -471,12 +542,12 @@ void PackTos::pack(OutputFile *fo)
|
|||||||
patchPackHeader(loader,o_text);
|
patchPackHeader(loader,o_text);
|
||||||
if (!opt->small)
|
if (!opt->small)
|
||||||
patchVersion(loader,o_text);
|
patchVersion(loader,o_text);
|
||||||
// patch "subq.l #1,d0" or "subq.w #1,d0" - see "up41" below
|
// patch "subq.l #1,d6" or "subq.w #1,d6" - see "up41" below
|
||||||
const unsigned dirty_bss_d0 =
|
const unsigned dirty_bss_d6 =
|
||||||
patch_d0_subq(loader, o_text, dirty_bss / dirty_bss_align, "u4");
|
patch_d_subq(loader, o_text, REG_D6, dirty_bss / dirty_bss_align, "u4");
|
||||||
patch_be32(loader, o_text, "up31", d_off + offset + decomp_offset);
|
patch_be32(loader, o_text, "up31", d_off + offset + decomp_offset);
|
||||||
if (opt->small)
|
if (opt->small)
|
||||||
patch_d0_loop(loader,o_text,o_data/4,"up22","u1");
|
patch_d_loop(loader, o_text, REG_D0, o_data/4, "up22", "u1");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (o_data <= 160)
|
if (o_data <= 160)
|
||||||
@@ -488,8 +559,8 @@ void PackTos::pack(OutputFile *fo)
|
|||||||
loop1--;
|
loop1--;
|
||||||
loop2 = 160;
|
loop2 = 160;
|
||||||
}
|
}
|
||||||
patch_be16(loader,o_text,"u2", 0x7000 + loop2/4-1); // moveq.l #X,d0
|
patch_be16(loader, o_text, "u2", OP_MOVEQ(loop2/4-1, REG_D0)); // moveq.l #X,d0
|
||||||
patch_d0_loop(loader,o_text,loop1,"up22","u1");
|
patch_d_loop(loader, o_text, REG_D0, loop1, "up22", "u1");
|
||||||
}
|
}
|
||||||
patch_be32(loader,o_text,"up21",o_data + offset);
|
patch_be32(loader,o_text,"up21",o_data + offset);
|
||||||
patch_be32(loader,o_text,"up13",i_bss); // p_blen
|
patch_be32(loader,o_text,"up13",i_bss); // p_blen
|
||||||
@@ -498,9 +569,9 @@ void PackTos::pack(OutputFile *fo)
|
|||||||
|
|
||||||
// patch decompressor
|
// patch decompressor
|
||||||
upx_byte *p = obuf + d_off;
|
upx_byte *p = obuf + d_off;
|
||||||
// patch "moveq.l #1,d3" or "jmp (a5)"
|
// patch "moveq.l #1,d5" or "jmp (ASTACK)"
|
||||||
patch_be16(p,d_len,"u3", (nrelocs > 0) ? 0x7601 : 0x4ed5);
|
patch_be16(p, d_len, "u3", (nrelocs > 0) ? OP_MOVEQ(1, REG_D5) : OP_JMP(REG_A7));
|
||||||
patch_be32(p,d_len,"up41", dirty_bss_d0);
|
patch_be32(p, d_len, "up41", dirty_bss_d6);
|
||||||
|
|
||||||
// set new file_hdr
|
// set new file_hdr
|
||||||
memcpy(&oh, &ih, FH_SIZE);
|
memcpy(&oh, &ih, FH_SIZE);
|
||||||
@@ -539,7 +610,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();
|
||||||
|
|
||||||
// copy the overlay
|
// copy the overlay
|
||||||
copyOverlay(fo, overlay, &obuf);
|
copyOverlay(fo, overlay, &obuf);
|
||||||
@@ -558,7 +629,7 @@ int PackTos::canUnpack()
|
|||||||
{
|
{
|
||||||
if (!readFileHeader())
|
if (!readFileHeader())
|
||||||
return false;
|
return false;
|
||||||
if (!readPackHeader(512))
|
if (!readPackHeader(768))
|
||||||
return false;
|
return false;
|
||||||
// check header as set by packer
|
// check header as set by packer
|
||||||
if ((ih.fh_text & 3) != 0 || (ih.fh_data & 3) != 0 || (ih.fh_bss & 3) != 0
|
if ((ih.fh_text & 3) != 0 || (ih.fh_data & 3) != 0 || (ih.fh_bss & 3) != 0
|
||||||
|
|||||||
+13
-10
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -39,10 +39,10 @@ class PackTos : public Packer
|
|||||||
typedef Packer super;
|
typedef Packer super;
|
||||||
public:
|
public:
|
||||||
PackTos(InputFile *f);
|
PackTos(InputFile *f);
|
||||||
virtual int getVersion() const { return 11; }
|
virtual int getVersion() const { return 13; }
|
||||||
virtual int getFormat() const { return UPX_F_ATARI_TOS; }
|
virtual int getFormat() const { return UPX_F_ATARI_TOS; }
|
||||||
virtual const char *getName() const { return "atari/tos"; }
|
virtual const char *getName() const { return "atari/tos"; }
|
||||||
virtual int getCompressionMethod() const;
|
virtual const int *getCompressionMethods(int method, int level) const;
|
||||||
virtual const int *getFilters() const;
|
virtual const int *getFilters() const;
|
||||||
|
|
||||||
virtual void pack(OutputFile *fo);
|
virtual void pack(OutputFile *fo);
|
||||||
@@ -57,8 +57,8 @@ protected:
|
|||||||
virtual const upx_byte *getLoader() const;
|
virtual const upx_byte *getLoader() const;
|
||||||
virtual int getLoaderSize() const;
|
virtual int getLoaderSize() const;
|
||||||
|
|
||||||
bool readFileHeader();
|
virtual int readFileHeader();
|
||||||
bool checkFileHeader();
|
virtual bool checkFileHeader();
|
||||||
|
|
||||||
struct tos_header_t
|
struct tos_header_t
|
||||||
{
|
{
|
||||||
@@ -70,11 +70,14 @@ protected:
|
|||||||
BE32 fh_reserved;
|
BE32 fh_reserved;
|
||||||
BE32 fh_flag;
|
BE32 fh_flag;
|
||||||
BE16 fh_reloc;
|
BE16 fh_reloc;
|
||||||
} ih, oh;
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
|
tos_header_t ih, oh;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
unsigned patch_d0_subq(void *b, int blen, unsigned, const char*);
|
unsigned patch_d_subq(void *l, int llen, int, unsigned, const char*);
|
||||||
unsigned patch_d0_loop(void *b, int blen, unsigned, const char*, const char*);
|
unsigned patch_d_loop(void *l, int llen, int, unsigned, const char*, const char*);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+221
-309
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,13 +22,14 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
#include "filter.h"
|
||||||
#include "packer.h"
|
#include "packer.h"
|
||||||
#include "p_unix.h"
|
#include "p_unix.h"
|
||||||
#include "p_elf.h"
|
#include "p_elf.h"
|
||||||
@@ -44,10 +45,11 @@
|
|||||||
PackUnix::PackUnix(InputFile *f) :
|
PackUnix::PackUnix(InputFile *f) :
|
||||||
super(f), exetype(0), blocksize(0), overlay_offset(0), lsize(0)
|
super(f), exetype(0), blocksize(0), overlay_offset(0), lsize(0)
|
||||||
{
|
{
|
||||||
assert(sizeof(Elf_LE32_Ehdr) == 52);
|
COMPILE_TIME_ASSERT(sizeof(Elf_LE32_Ehdr) == 52);
|
||||||
assert(sizeof(Elf_LE32_Phdr) == 32);
|
COMPILE_TIME_ASSERT(sizeof(Elf_LE32_Phdr) == 32);
|
||||||
assert(sizeof(l_info) == 12);
|
COMPILE_TIME_ASSERT(sizeof(b_info) == 12);
|
||||||
assert(sizeof(p_info) == 12);
|
COMPILE_TIME_ASSERT(sizeof(l_info) == 12);
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(p_info) == 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -67,15 +69,34 @@ bool PackUnix::canPack()
|
|||||||
|
|
||||||
// info: currently the header is 36 (32+4) bytes before EOF
|
// info: currently the header is 36 (32+4) bytes before EOF
|
||||||
unsigned char buf[256];
|
unsigned char buf[256];
|
||||||
fi->seek(-(long)sizeof(buf), SEEK_END);
|
fi->seek(-(off_t)sizeof(buf), SEEK_END);
|
||||||
fi->readx(buf, sizeof(buf));
|
fi->readx(buf, sizeof(buf));
|
||||||
if (find_le32(buf,sizeof(buf),UPX_MAGIC_LE32) >= 0) // note: always le32
|
checkAlreadyPacked(buf, sizeof(buf));
|
||||||
throwAlreadyPacked();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PackUnix::writePackHeader(OutputFile *fo)
|
||||||
|
{
|
||||||
|
unsigned char buf[32];
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
const int hsize = ph.getPackHeaderSize();
|
||||||
|
assert((unsigned)hsize <= sizeof(buf));
|
||||||
|
|
||||||
|
// note: magic constants are always le32
|
||||||
|
set_le32(buf+0, UPX_MAGIC_LE32);
|
||||||
|
set_le32(buf+4, UPX_MAGIC2_LE32);
|
||||||
|
|
||||||
|
checkPatch(NULL, 0, 0, 0); // reset
|
||||||
|
patchPackHeader(buf, hsize);
|
||||||
|
checkPatch(NULL, 0, 0, 0); // reset
|
||||||
|
|
||||||
|
fo->write(buf, hsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// Generic Unix pack(). Subclasses must provide patchLoader().
|
// Generic Unix pack(). Subclasses must provide patchLoader().
|
||||||
//
|
//
|
||||||
@@ -94,107 +115,170 @@ bool PackUnix::checkCompressionRatio(unsigned, unsigned) const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PackUnix::pack1(OutputFile * /*fo*/, Filter & /*ft*/)
|
||||||
|
{
|
||||||
|
// derived class usually provides this
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PackUnix::getStrategy(Filter &/*ft*/)
|
||||||
|
{
|
||||||
|
// Called just before reading and compressing each block.
|
||||||
|
// Might want to adjust blocksize, etc.
|
||||||
|
|
||||||
|
// If user specified the filter, then use it (-2==strategy).
|
||||||
|
// Else try the first two filters, and pick the better (2==strategy).
|
||||||
|
return ((opt->filter > 0) ? -2 : 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PackUnix::pack2(OutputFile *fo, Filter &ft)
|
||||||
|
{
|
||||||
|
// compress blocks
|
||||||
|
unsigned total_in = 0;
|
||||||
|
unsigned total_out = 0;
|
||||||
|
|
||||||
|
// FIXME: ui_total_passes is not correct with multiple blocks...
|
||||||
|
// ui_total_passes = (file_size + blocksize - 1) / blocksize;
|
||||||
|
// if (ui_total_passes == 1)
|
||||||
|
// ui_total_passes = 0;
|
||||||
|
|
||||||
|
unsigned remaining = file_size;
|
||||||
|
while (remaining > 0)
|
||||||
|
{
|
||||||
|
// FIXME: disable filters if we have more than one block.
|
||||||
|
// FIXME: There is only 1 un-filter in the stub [as of 2002-11-10].
|
||||||
|
// So the next block really has no choice!
|
||||||
|
// This merely prevents an assert() in compressWithFilters(),
|
||||||
|
// which assumes it has free choice on each call [block].
|
||||||
|
// And if the choices aren't the same on each block,
|
||||||
|
// then un-filtering will give incorrect results.
|
||||||
|
int strategy = getStrategy(ft);
|
||||||
|
if (file_size > (off_t)blocksize)
|
||||||
|
strategy = -3; // no filters
|
||||||
|
|
||||||
|
int l = fi->readx(ibuf, UPX_MIN(blocksize, remaining));
|
||||||
|
remaining -= l;
|
||||||
|
|
||||||
|
// Note: compression for a block can fail if the
|
||||||
|
// file is e.g. blocksize + 1 bytes long
|
||||||
|
|
||||||
|
// compress
|
||||||
|
ph.overlap_overhead = 0;
|
||||||
|
ph.c_len = ph.u_len = l;
|
||||||
|
ft.buf_len = l;
|
||||||
|
|
||||||
|
// compressWithFilters() updates u_adler _inside_ compress();
|
||||||
|
// that is, AFTER filtering. We want BEFORE filtering,
|
||||||
|
// so that decompression checks the end-to-end checksum.
|
||||||
|
unsigned const end_u_adler = upx_adler32(ibuf, ph.u_len, ph.u_adler);
|
||||||
|
compressWithFilters(&ft, OVERHEAD, strategy);
|
||||||
|
|
||||||
|
if (ph.c_len < ph.u_len) {
|
||||||
|
ph.overlap_overhead = OVERHEAD;
|
||||||
|
if (!testOverlappingDecompression(obuf, ph.overlap_overhead)) {
|
||||||
|
// not in-place compressible
|
||||||
|
ph.c_len = ph.u_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ph.c_len >= ph.u_len) {
|
||||||
|
// block is not compressible
|
||||||
|
ph.c_len = ph.u_len;
|
||||||
|
// must manually update checksum of compressed data
|
||||||
|
ph.c_adler = upx_adler32(ibuf, ph.u_len, ph.saved_c_adler);
|
||||||
|
}
|
||||||
|
|
||||||
|
// write block header
|
||||||
|
b_info blk_info;
|
||||||
|
memset(&blk_info, 0, sizeof(blk_info));
|
||||||
|
set_native32(&blk_info.sz_unc, ph.u_len);
|
||||||
|
set_native32(&blk_info.sz_cpr, ph.c_len);
|
||||||
|
if (ph.c_len < ph.u_len) {
|
||||||
|
blk_info.b_method = (unsigned char) ph.method;
|
||||||
|
blk_info.b_ftid = (unsigned char) ph.filter;
|
||||||
|
blk_info.b_cto8 = (unsigned char) ph.filter_cto;
|
||||||
|
}
|
||||||
|
fo->write(&blk_info, sizeof(blk_info));
|
||||||
|
b_len += sizeof(b_info);
|
||||||
|
|
||||||
|
// write compressed data
|
||||||
|
if (ph.c_len < ph.u_len) {
|
||||||
|
fo->write(obuf, ph.c_len);
|
||||||
|
verifyOverlappingDecompression(); // uses ph.u_adler
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fo->write(ibuf, ph.u_len);
|
||||||
|
}
|
||||||
|
ph.u_adler = end_u_adler;
|
||||||
|
|
||||||
|
total_in += ph.u_len;
|
||||||
|
total_out += ph.c_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update header with totals
|
||||||
|
ph.u_len = total_in;
|
||||||
|
ph.c_len = total_out;
|
||||||
|
|
||||||
|
if ((off_t)total_in != file_size) {
|
||||||
|
throwEOFException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PackUnix::pack3(OutputFile *fo, Filter &ft)
|
||||||
|
{
|
||||||
|
upx_byte const *p = getLoader();
|
||||||
|
lsize = getLoaderSize();
|
||||||
|
patchFilter32(const_cast<upx_byte *>(p), lsize, &ft);
|
||||||
|
updateLoader(fo);
|
||||||
|
patchLoaderChecksum();
|
||||||
|
fo->write(p, lsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PackUnix::pack4(OutputFile *fo, Filter &)
|
||||||
|
{
|
||||||
|
writePackHeader(fo);
|
||||||
|
|
||||||
|
unsigned tmp;
|
||||||
|
set_native32(&tmp, overlay_offset);
|
||||||
|
fo->write(&tmp, sizeof(tmp));
|
||||||
|
}
|
||||||
|
|
||||||
void PackUnix::pack(OutputFile *fo)
|
void PackUnix::pack(OutputFile *fo)
|
||||||
{
|
{
|
||||||
|
Filter ft(ph.level);
|
||||||
|
ft.addvalue = 0;
|
||||||
|
b_len = 0;
|
||||||
|
progid = 0;
|
||||||
|
|
||||||
// set options
|
// set options
|
||||||
blocksize = opt->unix.blocksize;
|
blocksize = opt->unix.blocksize;
|
||||||
if (blocksize <= 0)
|
if (blocksize <= 0)
|
||||||
blocksize = BLOCKSIZE;
|
blocksize = BLOCKSIZE;
|
||||||
if ((off_t)blocksize > file_size)
|
if ((off_t)blocksize > file_size)
|
||||||
blocksize = file_size;
|
blocksize = file_size;
|
||||||
// create a pseudo-unique program id for our paranoid stub
|
|
||||||
progid = getRandomId();
|
|
||||||
|
|
||||||
// prepare loader
|
|
||||||
lsize = getLoaderSize();
|
|
||||||
loader.alloc(lsize + sizeof(p_info));
|
|
||||||
memcpy(loader,getLoader(),lsize);
|
|
||||||
|
|
||||||
// patch loader, prepare header info
|
|
||||||
patchLoader(); // can change lsize by packing C-code of upx_main etc.
|
|
||||||
p_info *const hbuf = (p_info *)(loader + lsize);
|
|
||||||
set_native32(&hbuf->p_progid, progid);
|
|
||||||
set_native32(&hbuf->p_filesize, file_size);
|
|
||||||
set_native32(&hbuf->p_blocksize, blocksize);
|
|
||||||
fo->write(loader, lsize + sizeof(p_info));
|
|
||||||
|
|
||||||
// init compression buffers
|
// init compression buffers
|
||||||
ibuf.alloc(blocksize);
|
ibuf.alloc(blocksize);
|
||||||
obuf.allocForCompression(blocksize);
|
obuf.allocForCompression(blocksize);
|
||||||
|
|
||||||
// compress blocks
|
|
||||||
unsigned total_in = 0;
|
|
||||||
unsigned total_out = 0;
|
|
||||||
ui_total_passes = (file_size + blocksize - 1) / blocksize;
|
|
||||||
if (ui_total_passes == 1)
|
|
||||||
ui_total_passes = 0;
|
|
||||||
fi->seek(0, SEEK_SET);
|
fi->seek(0, SEEK_SET);
|
||||||
for (;;)
|
pack1(fo, ft); // generate Elf header, etc.
|
||||||
{
|
|
||||||
int l = fi->read(ibuf, blocksize);
|
|
||||||
if (l == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Note: compression for a block can fail if the
|
p_info hbuf;
|
||||||
// file is e.g. blocksize + 1 bytes long
|
set_native32(&hbuf.p_progid, progid);
|
||||||
|
set_native32(&hbuf.p_filesize, file_size);
|
||||||
|
set_native32(&hbuf.p_blocksize, blocksize);
|
||||||
|
fo->write(&hbuf, sizeof(hbuf));
|
||||||
|
|
||||||
// compress
|
pack2(fo, ft); // append the compressed body
|
||||||
ph.u_len = l;
|
|
||||||
(void) compress(ibuf, obuf); // ignore return value
|
|
||||||
|
|
||||||
if (ph.c_len < ph.u_len)
|
|
||||||
{
|
|
||||||
if (!testOverlappingDecompression(obuf, OVERHEAD))
|
|
||||||
throwNotCompressible();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// block is not compressible
|
|
||||||
ph.c_len = ph.u_len;
|
|
||||||
// must manually update checksum of compressed data
|
|
||||||
ph.c_adler = upx_adler32(ph.c_adler, ibuf, ph.u_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
// write block sizes
|
|
||||||
unsigned char size[8];
|
|
||||||
set_native32(size+0, ph.u_len);
|
|
||||||
set_native32(size+4, ph.c_len);
|
|
||||||
fo->write(size, 8);
|
|
||||||
|
|
||||||
// write compressed data
|
|
||||||
if (ph.c_len < ph.u_len)
|
|
||||||
{
|
|
||||||
fo->write(obuf, ph.c_len);
|
|
||||||
verifyOverlappingDecompression(&obuf, OVERHEAD);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
fo->write(ibuf, ph.u_len);
|
|
||||||
|
|
||||||
total_in += ph.u_len;
|
|
||||||
total_out += ph.c_len;
|
|
||||||
}
|
|
||||||
if ((off_t)total_in != file_size)
|
|
||||||
throwEOFException();
|
|
||||||
|
|
||||||
// write block end marker (uncompressed size 0)
|
// write block end marker (uncompressed size 0)
|
||||||
fo->write("\x00\x00\x00\x00", 4);
|
b_info hdr; memset(&hdr, 0, sizeof(hdr));
|
||||||
|
set_le32(&hdr.sz_cpr, UPX_MAGIC_LE32);
|
||||||
|
fo->write(&hdr, sizeof(hdr));
|
||||||
|
|
||||||
// update header with totals
|
pack3(fo, ft); // append loader
|
||||||
ph.u_len = total_in;
|
|
||||||
ph.c_len = total_out;
|
|
||||||
|
|
||||||
// write packheader
|
pack4(fo, ft); // append PackHeader and overlay_offset; update Elf header
|
||||||
const int hsize = ph.getPackHeaderSize();
|
|
||||||
set_le32(obuf, ph.magic); // note: always le32
|
|
||||||
patchPackHeader(obuf, hsize);
|
|
||||||
fo->write(obuf, hsize);
|
|
||||||
|
|
||||||
// write overlay offset (needed for decompression)
|
|
||||||
set_native32(obuf, lsize);
|
|
||||||
fo->write(obuf, 4);
|
|
||||||
|
|
||||||
updateLoader(fo);
|
|
||||||
|
|
||||||
// finally check the compression ratio
|
// finally check the compression ratio
|
||||||
if (!checkFinalCompressionRatio(fo))
|
if (!checkFinalCompressionRatio(fo))
|
||||||
@@ -236,8 +320,28 @@ int PackUnix::canUnpack()
|
|||||||
|
|
||||||
void PackUnix::unpack(OutputFile *fo)
|
void PackUnix::unpack(OutputFile *fo)
|
||||||
{
|
{
|
||||||
unsigned c_adler = upx_adler32(0, NULL, 0);
|
unsigned szb_info = sizeof(b_info);
|
||||||
unsigned u_adler = upx_adler32(0, NULL, 0);
|
{
|
||||||
|
Elf_LE32_Ehdr ehdr;
|
||||||
|
fi->seek(0, SEEK_SET);
|
||||||
|
fi->readx(&ehdr, sizeof(ehdr));
|
||||||
|
unsigned const e_entry = get_native32(&ehdr.e_entry);
|
||||||
|
if (e_entry < 0x401180) { /* old style, 8-byte b_info */
|
||||||
|
szb_info = 2*sizeof(unsigned);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Elf_LE32_Phdr phdr;
|
||||||
|
fi->seek(get_native32(&ehdr.e_phoff), SEEK_SET);
|
||||||
|
fi->readx(&phdr, sizeof(phdr));
|
||||||
|
unsigned const p_vaddr = get_native32(&phdr.p_vaddr);
|
||||||
|
if (0x80==(e_entry - p_vaddr)) { /* 1.22 old style */
|
||||||
|
szb_info = 2*sizeof(unsigned);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned c_adler = upx_adler32(NULL, 0);
|
||||||
|
unsigned u_adler = upx_adler32(NULL, 0);
|
||||||
|
|
||||||
// defaults for ph.version == 8
|
// defaults for ph.version == 8
|
||||||
unsigned orig_file_size = 0;
|
unsigned orig_file_size = 0;
|
||||||
@@ -265,46 +369,52 @@ void PackUnix::unpack(OutputFile *fo)
|
|||||||
// decompress blocks
|
// decompress blocks
|
||||||
unsigned total_in = 0;
|
unsigned total_in = 0;
|
||||||
unsigned total_out = 0;
|
unsigned total_out = 0;
|
||||||
|
b_info bhdr; memset(&bhdr, 0, sizeof(bhdr));
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
#define buf ibuf
|
#define buf ibuf
|
||||||
int i;
|
int i;
|
||||||
int size[2];
|
unsigned sz_unc, sz_cpr;
|
||||||
|
|
||||||
fi->readx(buf, 8);
|
fi->readx(&bhdr, szb_info);
|
||||||
ph.u_len = size[0] = get_native32(buf+0);
|
ph.u_len = sz_unc = get_native32(&bhdr.sz_unc);
|
||||||
ph.c_len = size[1] = get_native32(buf+4);
|
ph.c_len = sz_cpr = get_native32(&bhdr.sz_cpr);
|
||||||
|
|
||||||
if (size[0] == 0) // uncompressed size 0 -> EOF
|
if (sz_unc == 0) // uncompressed size 0 -> EOF
|
||||||
{
|
{
|
||||||
// note: must reload size[1] as magic is always stored le32
|
// note: must reload sz_cpr as magic is always stored le32
|
||||||
size[1] = get_le32(buf+4);
|
sz_cpr = get_le32(&bhdr.sz_cpr);
|
||||||
if (size[1] != UPX_MAGIC_LE32) // size[1] must be h->magic
|
if (sz_cpr != UPX_MAGIC_LE32) // sz_cpr must be h->magic
|
||||||
throwCompressedDataViolation();
|
throwCompressedDataViolation();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (size[0] <= 0 || size[1] <= 0)
|
if (sz_unc <= 0 || sz_cpr <= 0)
|
||||||
throwCompressedDataViolation();
|
throwCompressedDataViolation();
|
||||||
if (size[1] > size[0] || size[0] > (int)blocksize)
|
if (sz_cpr > sz_unc || sz_unc > blocksize)
|
||||||
throwCompressedDataViolation();
|
throwCompressedDataViolation();
|
||||||
|
|
||||||
i = blocksize + OVERHEAD - size[1];
|
i = blocksize + OVERHEAD - sz_cpr;
|
||||||
fi->readx(buf+i, size[1]);
|
fi->readx(buf+i, sz_cpr);
|
||||||
// update checksum of compressed data
|
// update checksum of compressed data
|
||||||
c_adler = upx_adler32(c_adler, buf + i, size[1]);
|
c_adler = upx_adler32(buf + i, sz_cpr, c_adler);
|
||||||
// decompress
|
// decompress
|
||||||
if (size[1] < size[0])
|
if (sz_cpr < sz_unc) {
|
||||||
{
|
|
||||||
decompress(buf+i, buf, false);
|
decompress(buf+i, buf, false);
|
||||||
|
if (0!=bhdr.b_ftid) {
|
||||||
|
Filter ft(ph.level);
|
||||||
|
ft.init(bhdr.b_ftid);
|
||||||
|
ft.cto = bhdr.b_cto8;
|
||||||
|
ft.unfilter(buf, sz_unc);
|
||||||
|
}
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
// update checksum of uncompressed data
|
// update checksum of uncompressed data
|
||||||
u_adler = upx_adler32(u_adler, buf + i, size[0]);
|
u_adler = upx_adler32(buf + i, sz_unc, u_adler);
|
||||||
total_in += size[1];
|
total_in += sz_cpr;
|
||||||
total_out += size[0];
|
total_out += sz_unc;
|
||||||
// write block
|
// write block
|
||||||
if (fo)
|
if (fo)
|
||||||
fo->write(buf + i, size[0]);
|
fo->write(buf + i, sz_unc);
|
||||||
#undef buf
|
#undef buf
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,204 +432,6 @@ void PackUnix::unpack(OutputFile *fo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
// linux/i386 (generic "execve" format)
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
static const
|
|
||||||
#include "stub/l_lx_n2b.h"
|
|
||||||
static const
|
|
||||||
#include "stub/l_lx_n2d.h"
|
|
||||||
|
|
||||||
|
|
||||||
int PackLinuxI386::getCompressionMethod() const
|
|
||||||
{
|
|
||||||
if (M_IS_NRV2B(opt->method))
|
|
||||||
return M_NRV2B_LE32;
|
|
||||||
if (M_IS_NRV2D(opt->method))
|
|
||||||
return M_NRV2D_LE32;
|
|
||||||
return opt->level > 1 && file_size >= 512*1024 ? M_NRV2D_LE32 : M_NRV2B_LE32;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const upx_byte *PackLinuxI386::getLoader() const
|
|
||||||
{
|
|
||||||
if (M_IS_NRV2B(opt->method))
|
|
||||||
return linux_i386exec_nrv2b_loader;
|
|
||||||
if (M_IS_NRV2D(opt->method))
|
|
||||||
return linux_i386exec_nrv2d_loader;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int PackLinuxI386::getLoaderSize() const
|
|
||||||
{
|
|
||||||
if (0!=lsize) {
|
|
||||||
return lsize;
|
|
||||||
}
|
|
||||||
if (M_IS_NRV2B(opt->method))
|
|
||||||
return sizeof(linux_i386exec_nrv2b_loader);
|
|
||||||
if (M_IS_NRV2D(opt->method))
|
|
||||||
return sizeof(linux_i386exec_nrv2d_loader);
|
|
||||||
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;
|
|
||||||
|
|
||||||
fi->readx(&ehdr, sizeof(ehdr));
|
|
||||||
fi->seek(0, SEEK_SET);
|
|
||||||
|
|
||||||
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
|
|
||||||
exetype = 0;
|
|
||||||
if (ehdr.e_type != 2) // executable
|
|
||||||
exetype = 0;
|
|
||||||
if (ehdr.e_machine != 3 && ehdr.e_machine != 6) // Intel 80[34]86
|
|
||||||
exetype = 0;
|
|
||||||
if (ehdr.e_version != 1) // version
|
|
||||||
exetype = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
if (l == 0x00640107 || l == 0x00640108 || l == 0x0064010b || l == 0x006400cc)
|
|
||||||
{
|
|
||||||
// OMAGIC / NMAGIC / ZMAGIC / QMAGIC
|
|
||||||
exetype = 2;
|
|
||||||
// FIXME: N_TRSIZE, N_DRSIZE
|
|
||||||
// FIXME: check for aout shared libraries
|
|
||||||
}
|
|
||||||
#if defined(__linux__)
|
|
||||||
// only compress scripts when running under Linux
|
|
||||||
else if (!memcmp(buf, "#!/", 3)) // #!/bin/sh
|
|
||||||
exetype = -1;
|
|
||||||
else if (!memcmp(buf, "#! /", 4)) // #! /bin/sh
|
|
||||||
exetype = -1;
|
|
||||||
else if (!memcmp(buf, "\xca\xfe\xba\xbe", 4)) // Java bytecode
|
|
||||||
exetype = -2;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return super::canPack();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PackLinuxI386::patchLoader()
|
|
||||||
{
|
|
||||||
lsize = getLoaderSize();
|
|
||||||
|
|
||||||
// patch loader
|
|
||||||
// note: we only can use /proc/<pid>/fd when exetype > 0.
|
|
||||||
// also, we sleep much longer when compressing a script.
|
|
||||||
patch_le32(loader,lsize,"UPX4",exetype > 0 ? 3 : 15); // sleep time
|
|
||||||
patch_le32(loader,lsize,"UPX3",exetype > 0 ? 0 : 0x7fffffff);
|
|
||||||
patch_le32(loader,lsize,"UPX2",progid);
|
|
||||||
patchVersion(loader,lsize);
|
|
||||||
|
|
||||||
Elf_LE32_Ehdr *const ehdr = (Elf_LE32_Ehdr *)(void *)loader;
|
|
||||||
Elf_LE32_Phdr *const phdr = (Elf_LE32_Phdr *)(1+ehdr);
|
|
||||||
|
|
||||||
// stub/scripts/setfold.pl puts address of 'fold_begin' in phdr[1].p_offset
|
|
||||||
off_t const fold_begin = phdr[1].p_offset;
|
|
||||||
assert(fold_begin > 0);
|
|
||||||
assert(fold_begin < (off_t)lsize);
|
|
||||||
MemBuffer cprLoader(lsize);
|
|
||||||
|
|
||||||
// compress compiled C-code portion of loader
|
|
||||||
upx_compress_config_t conf; memset(&conf, 0xff, sizeof(conf));
|
|
||||||
conf.c_flags = 0;
|
|
||||||
upx_uint result_buffer[16];
|
|
||||||
upx_uint const uncLsize = lsize - fold_begin;
|
|
||||||
upx_uint cprLsize;
|
|
||||||
upx_compress(
|
|
||||||
loader + fold_begin, uncLsize,
|
|
||||||
cprLoader, &cprLsize,
|
|
||||||
0, // progress_callback_t ??
|
|
||||||
getCompressionMethod(), 9,
|
|
||||||
&conf,
|
|
||||||
result_buffer
|
|
||||||
);
|
|
||||||
memcpy(fold_begin+loader, cprLoader, cprLsize);
|
|
||||||
lsize = fold_begin + cprLsize;
|
|
||||||
phdr->p_filesz = lsize;
|
|
||||||
// phdr->p_memsz is the decompressed size
|
|
||||||
|
|
||||||
// The beginning of our loader consists of a elf_hdr (52 bytes) and
|
|
||||||
// one section elf_phdr (32 byte) now,
|
|
||||||
// another section elf_phdr (32 byte) later, so we have 12 free bytes
|
|
||||||
// from offset 116 to the program start at offset 128.
|
|
||||||
// These 12 bytes are used for l_info by ::patchLoaderChecksum().
|
|
||||||
assert(get_le32(loader + 28) == 52); // e_phoff
|
|
||||||
assert(get_le32(loader + 32) == 0); // e_shoff
|
|
||||||
assert(get_le16(loader + 40) == 52); // e_ehsize
|
|
||||||
assert(get_le16(loader + 42) == 32); // e_phentsize
|
|
||||||
assert(get_le16(loader + 44) == 1); // e_phnum
|
|
||||||
assert(get_le16(loader + 48) == 0); // e_shnum
|
|
||||||
assert(lsize > 128 && lsize < 4096);
|
|
||||||
|
|
||||||
patchLoaderChecksum();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PackLinuxI386::patchLoaderChecksum()
|
|
||||||
{
|
|
||||||
l_info *const lp = (l_info *)(loader + getLoaderPrefixSize());
|
|
||||||
// checksum for loader + p_info
|
|
||||||
lp->l_checksum = 0; // (this checksum is currently unused)
|
|
||||||
lp->l_magic = UPX_ELF_MAGIC;
|
|
||||||
lp->l_lsize = (unsigned short) lsize;
|
|
||||||
lp->l_version = (unsigned char) ph.version;
|
|
||||||
lp->l_format = (unsigned char) ph.format;
|
|
||||||
unsigned adler = upx_adler32(0,NULL,0);
|
|
||||||
adler = upx_adler32(adler, loader, lsize + sizeof(p_info));
|
|
||||||
lp->l_checksum = adler;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PackLinuxI386::updateLoader(OutputFile *fo)
|
|
||||||
{
|
|
||||||
#define PAGE_MASK (~0<<12)
|
|
||||||
Elf_LE32_Ehdr *ehdr = (Elf_LE32_Ehdr *)(unsigned char *)loader;
|
|
||||||
ehdr->e_phnum = 2;
|
|
||||||
|
|
||||||
// The first Phdr maps the stub (instructions, data, bss) rwx.
|
|
||||||
// The second Phdr maps the overlay r--,
|
|
||||||
// to defend against /usr/bin/strip removing the overlay.
|
|
||||||
Elf_LE32_Phdr *const phdro = 1+(Elf_LE32_Phdr *)(1+ehdr);
|
|
||||||
|
|
||||||
phdro->p_type = PT_LOAD;
|
|
||||||
phdro->p_offset = lsize;
|
|
||||||
phdro->p_paddr = phdro->p_vaddr = 0x00400000 + (lsize &~ PAGE_MASK);
|
|
||||||
phdro->p_memsz = phdro->p_filesz = fo->getBytesWritten() - lsize;
|
|
||||||
phdro->p_flags = PF_R;
|
|
||||||
phdro->p_align = -PAGE_MASK;
|
|
||||||
|
|
||||||
patchLoaderChecksum();
|
|
||||||
fo->seek(0, SEEK_SET);
|
|
||||||
fo->rewrite(loader, 0x80);
|
|
||||||
#undef PAGE_MASK
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
vi:ts=4:et
|
vi:ts=4:et
|
||||||
*/
|
*/
|
||||||
|
|||||||
+43
-47
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -41,8 +41,9 @@ class PackUnix : public Packer
|
|||||||
protected:
|
protected:
|
||||||
PackUnix(InputFile *f);
|
PackUnix(InputFile *f);
|
||||||
public:
|
public:
|
||||||
virtual int getVersion() const { return 11; }
|
virtual int getVersion() const { return 13; }
|
||||||
virtual const int *getFilters() const { return NULL; }
|
virtual const int *getFilters() const { return NULL; }
|
||||||
|
virtual int getStrategy(Filter &);
|
||||||
|
|
||||||
virtual void pack(OutputFile *fo);
|
virtual void pack(OutputFile *fo);
|
||||||
virtual void unpack(OutputFile *fo);
|
virtual void unpack(OutputFile *fo);
|
||||||
@@ -52,14 +53,21 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
// called by the generic pack()
|
// called by the generic pack()
|
||||||
|
virtual void pack1(OutputFile *, Filter &); // generate executable header
|
||||||
|
virtual void pack2(OutputFile *, Filter &); // append compressed data
|
||||||
|
virtual void pack3(OutputFile *, Filter &); // append loader
|
||||||
|
virtual void pack4(OutputFile *, Filter &); // append PackHeader
|
||||||
|
|
||||||
virtual void patchLoader() = 0;
|
virtual void patchLoader() = 0;
|
||||||
virtual void patchLoaderChecksum() {}
|
virtual void patchLoaderChecksum() {}
|
||||||
virtual void updateLoader(OutputFile *) = 0;
|
virtual void updateLoader(OutputFile *) = 0;
|
||||||
|
|
||||||
|
virtual void writePackHeader(OutputFile *fo);
|
||||||
|
|
||||||
// in order too share as much code as possible we introduce
|
// in order too share as much code as possible we introduce
|
||||||
// an endian abstraction here
|
// an endian abstraction here
|
||||||
virtual unsigned get_native32(const void *, int off=0) = 0;
|
virtual unsigned get_native32(const void *) = 0;
|
||||||
virtual void set_native32(void *, unsigned, int off=0) = 0;
|
virtual void set_native32(void *, unsigned) = 0;
|
||||||
|
|
||||||
virtual bool checkCompressionRatio(unsigned, unsigned) const;
|
virtual bool checkCompressionRatio(unsigned, unsigned) const;
|
||||||
|
|
||||||
@@ -70,6 +78,21 @@ protected:
|
|||||||
|
|
||||||
MemBuffer loader;
|
MemBuffer loader;
|
||||||
int lsize;
|
int lsize;
|
||||||
|
MemBuffer pt_dynamic;
|
||||||
|
int sz_dynamic;
|
||||||
|
|
||||||
|
unsigned b_len; // total length of b_info blocks
|
||||||
|
|
||||||
|
// must agree with stub/linux.hh
|
||||||
|
struct b_info { // 12-byte header before each compressed block
|
||||||
|
unsigned sz_unc; // uncompressed_size
|
||||||
|
unsigned sz_cpr; // compressed_size
|
||||||
|
unsigned char b_method; // compression algorithm
|
||||||
|
unsigned char b_ftid; // filter id
|
||||||
|
unsigned char b_cto8; // filter parameter
|
||||||
|
unsigned char b_unused;
|
||||||
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
struct l_info { // 12-byte trailer in header for loader
|
struct l_info { // 12-byte trailer in header for loader
|
||||||
unsigned l_checksum;
|
unsigned l_checksum;
|
||||||
@@ -77,12 +100,15 @@ protected:
|
|||||||
unsigned short l_lsize;
|
unsigned short l_lsize;
|
||||||
unsigned char l_version;
|
unsigned char l_version;
|
||||||
unsigned char l_format;
|
unsigned char l_format;
|
||||||
};
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
struct p_info { // 12-byte packed program header
|
struct p_info { // 12-byte packed program header
|
||||||
unsigned p_progid;
|
unsigned p_progid;
|
||||||
unsigned p_filesize;
|
unsigned p_filesize;
|
||||||
unsigned p_blocksize;
|
unsigned p_blocksize;
|
||||||
};
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
// do not change !!!
|
// do not change !!!
|
||||||
enum { OVERHEAD = 2048 };
|
enum { OVERHEAD = 2048 };
|
||||||
@@ -99,13 +125,13 @@ class PackUnixBe32 : public PackUnix
|
|||||||
typedef PackUnix super;
|
typedef PackUnix super;
|
||||||
protected:
|
protected:
|
||||||
PackUnixBe32(InputFile *f) : super(f) { }
|
PackUnixBe32(InputFile *f) : super(f) { }
|
||||||
virtual unsigned get_native32(const void * b, int off=0)
|
virtual unsigned get_native32(const void *b)
|
||||||
{
|
{
|
||||||
return get_be32(b, off);
|
return get_be32(b);
|
||||||
}
|
}
|
||||||
virtual void set_native32(void * b, unsigned v, int off=0)
|
virtual void set_native32(void *b, unsigned v)
|
||||||
{
|
{
|
||||||
set_be32(b, v, off);
|
set_be32(b, v);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -115,47 +141,17 @@ class PackUnixLe32 : public PackUnix
|
|||||||
typedef PackUnix super;
|
typedef PackUnix super;
|
||||||
protected:
|
protected:
|
||||||
PackUnixLe32(InputFile *f) : super(f) { }
|
PackUnixLe32(InputFile *f) : super(f) { }
|
||||||
virtual unsigned get_native32(const void * b, int off=0)
|
virtual unsigned get_native32(const void *b)
|
||||||
{
|
{
|
||||||
return get_le32(b, off);
|
return get_le32(b);
|
||||||
}
|
}
|
||||||
virtual void set_native32(void * b, unsigned v, int off=0)
|
virtual void set_native32(void *b, unsigned v)
|
||||||
{
|
{
|
||||||
set_le32(b, v, off);
|
set_le32(b, v);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
// linux/i386 (generic "execve" format)
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
class PackLinuxI386 : public PackUnixLe32
|
|
||||||
{
|
|
||||||
typedef PackUnixLe32 super;
|
|
||||||
public:
|
|
||||||
PackLinuxI386(InputFile *f) : super(f) { }
|
|
||||||
virtual int getFormat() const { return UPX_F_LINUX_i386; }
|
|
||||||
virtual const char *getName() const { return "linux/386"; }
|
|
||||||
virtual int getCompressionMethod() const;
|
|
||||||
|
|
||||||
virtual bool canPack();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual const upx_byte *getLoader() const;
|
|
||||||
virtual int getLoaderSize() const;
|
|
||||||
virtual int getLoaderPrefixSize() const;
|
|
||||||
|
|
||||||
virtual void patchLoader();
|
|
||||||
virtual void patchLoaderChecksum();
|
|
||||||
virtual void updateLoader(OutputFile *);
|
|
||||||
|
|
||||||
enum {
|
|
||||||
UPX_ELF_MAGIC = 0x5850557f // "\x7fUPX"
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// solaris/sparc
|
// solaris/sparc
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
@@ -177,7 +173,7 @@ protected:
|
|||||||
|
|
||||||
virtual void patchLoader();
|
virtual void patchLoader();
|
||||||
};
|
};
|
||||||
#endif
|
#endif /* #if 0 */
|
||||||
|
|
||||||
|
|
||||||
#endif /* already included */
|
#endif /* already included */
|
||||||
|
|||||||
+142
-69
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -52,24 +52,21 @@ static const unsigned bzimage_offset = 0x100000;
|
|||||||
PackVmlinuzI386::PackVmlinuzI386(InputFile *f) :
|
PackVmlinuzI386::PackVmlinuzI386(InputFile *f) :
|
||||||
super(f)
|
super(f)
|
||||||
{
|
{
|
||||||
assert(sizeof(boot_sect_t) == 0x218);
|
COMPILE_TIME_ASSERT(sizeof(boot_sect_t) == 0x218);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int PackVmlinuzI386::getCompressionMethod() const
|
const int *PackVmlinuzI386::getCompressionMethods(int method, int level) const
|
||||||
{
|
{
|
||||||
if (M_IS_NRV2B(opt->method))
|
return Packer::getDefaultCompressionMethods_le32(method, level);
|
||||||
return M_NRV2B_LE32;
|
|
||||||
if (M_IS_NRV2D(opt->method))
|
|
||||||
return M_NRV2D_LE32;
|
|
||||||
return opt->level > 1 ? M_NRV2D_LE32 : M_NRV2B_LE32;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const int *PackVmlinuzI386::getFilters() const
|
const int *PackVmlinuzI386::getFilters() const
|
||||||
{
|
{
|
||||||
static const int filters[] = { 0x26, 0x24, 0x11, 0x14, 0x13, 0x16,
|
static const int filters[] = {
|
||||||
0x25, 0x15, 0x12, -1 };
|
0x26, 0x24, 0x11, 0x14, 0x13, 0x16, 0x25, 0x15, 0x12,
|
||||||
|
-1 };
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,50 +85,125 @@ int PackVmlinuzI386::readFileHeader()
|
|||||||
{
|
{
|
||||||
boot_sect_t h;
|
boot_sect_t h;
|
||||||
|
|
||||||
|
setup_size = 0;
|
||||||
|
|
||||||
fi->readx(&h, sizeof(h));
|
fi->readx(&h, sizeof(h));
|
||||||
if (h.boot_flag != 0xAA55)
|
if (h.boot_flag != 0xAA55)
|
||||||
return -1;
|
return 0;
|
||||||
|
const bool hdrs = (memcmp(h.hdrs, "HdrS", 4) == 0);
|
||||||
|
|
||||||
setup_size = (1 + (h.setup_sects ? h.setup_sects : 4)) * 0x200;
|
setup_size = (1 + (h.setup_sects ? h.setup_sects : 4)) * 0x200;
|
||||||
if (setup_size <= 0 || setup_size >= file_size)
|
if (setup_size <= 0 || setup_size >= file_size)
|
||||||
return -1;
|
return 0;
|
||||||
if (setup_size + 16 * h.sys_size != (unsigned) ALIGN_UP(file_size, 16))
|
|
||||||
return -1;
|
int format = UPX_F_VMLINUZ_i386;
|
||||||
|
unsigned sys_size = ALIGN_UP(file_size, 16) - setup_size;
|
||||||
|
|
||||||
|
const unsigned char *p = (const unsigned char *) &h + 0x1e3;
|
||||||
|
|
||||||
|
if (hdrs && memcmp(p, "\x0d\x0a\x07""ELKS", 7) == 0)
|
||||||
|
{
|
||||||
|
format = UPX_F_ELKS_8086;
|
||||||
|
}
|
||||||
|
else if (hdrs && (h.load_flags & 1) != 0)
|
||||||
|
{
|
||||||
|
format = UPX_F_BVMLINUZ_i386;
|
||||||
|
// account for 16-bit h.sys_size, wrap around at 20 bits
|
||||||
|
sys_size &= (1 << 20) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (16u * h.sys_size != sys_size)
|
||||||
|
return 0;
|
||||||
|
|
||||||
// FIXME: add more checks for a valid kernel
|
// FIXME: add more checks for a valid kernel
|
||||||
|
|
||||||
if (memcmp(h.hdrs, "HdrS", 4) == 0 && (h.load_flags & 1) != 0)
|
return format;
|
||||||
return UPX_F_BVMLINUZ_i386;
|
|
||||||
|
|
||||||
return UPX_F_VMLINUZ_i386;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// read full kernel into obuf, gzip-uncompress into ibuf,
|
// read full kernel into obuf[], gzip-decompress into ibuf[],
|
||||||
// return uncompressed size
|
// return decompressed size
|
||||||
int PackVmlinuzI386::uncompressKernel()
|
int PackVmlinuzI386::decompressKernel()
|
||||||
{
|
{
|
||||||
// read whole kernel image
|
// read whole kernel image
|
||||||
obuf.alloc(file_size);
|
obuf.alloc(file_size);
|
||||||
fi->seek(0, SEEK_SET);
|
fi->seek(0, SEEK_SET);
|
||||||
fi->readx(obuf, file_size);
|
fi->readx(obuf, file_size);
|
||||||
|
|
||||||
// estimate gzip-uncompressed kernel size & alloc buffer
|
checkAlreadyPacked(obuf + setup_size, UPX_MIN(file_size - setup_size, 1024));
|
||||||
ibuf.alloc((file_size - setup_size) * 3);
|
|
||||||
|
|
||||||
// find gzip/zlib header
|
|
||||||
for (int gzoff = setup_size; gzoff < file_size; gzoff++)
|
for (int gzoff = setup_size; gzoff < file_size; gzoff++)
|
||||||
{
|
{
|
||||||
int off = find(obuf + gzoff, file_size - gzoff, "\x1F\x8B", 2);
|
// find gzip header (2 bytes magic + 1 byte method "deflated")
|
||||||
|
int off = find(obuf + gzoff, file_size - gzoff, "\x1F\x8B\x08", 3);
|
||||||
if (off < 0)
|
if (off < 0)
|
||||||
break;
|
break;
|
||||||
gzoff += off;
|
gzoff += off;
|
||||||
fi->seek(gzoff, SEEK_SET);
|
const int gzlen = file_size - gzoff;
|
||||||
gzFile zf = gzdopen(fi->getFd(), "r");
|
if (gzlen < 256)
|
||||||
if (zf == 0)
|
|
||||||
break;
|
break;
|
||||||
int klen = gzread(zf, ibuf, ibuf.getSize());
|
// check gzip flag byte
|
||||||
if (klen >= file_size)
|
unsigned char flags = obuf[gzoff + 3];
|
||||||
|
if ((flags & 0xe0) != 0) // reserved bits set
|
||||||
|
continue;
|
||||||
|
//printf("found gzip header at offset %d\n", gzoff);
|
||||||
|
|
||||||
|
// try to decompress
|
||||||
|
int klen;
|
||||||
|
int fd;
|
||||||
|
off_t fd_pos;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
klen = -1;
|
||||||
|
fd = -1;
|
||||||
|
fd_pos = -1;
|
||||||
|
// open
|
||||||
|
fi->seek(gzoff, SEEK_SET);
|
||||||
|
fd = dup(fi->getFd());
|
||||||
|
if (fd < 0)
|
||||||
|
break;
|
||||||
|
gzFile zf = gzdopen(fd, "r");
|
||||||
|
if (zf == NULL)
|
||||||
|
break;
|
||||||
|
// estimate gzip-decompressed kernel size & alloc buffer
|
||||||
|
if (ibuf.getSize() == 0)
|
||||||
|
ibuf.alloc(gzlen * 3);
|
||||||
|
// decompress
|
||||||
|
klen = gzread(zf, ibuf, ibuf.getSize());
|
||||||
|
fd_pos = lseek(fd, 0, SEEK_CUR);
|
||||||
|
gzclose(zf);
|
||||||
|
fd = -1;
|
||||||
|
if (klen != (int)ibuf.getSize())
|
||||||
|
break;
|
||||||
|
// realloc and try again
|
||||||
|
unsigned s = ibuf.getSize();
|
||||||
|
ibuf.dealloc();
|
||||||
|
ibuf.alloc(3 * s / 2);
|
||||||
|
}
|
||||||
|
if (fd >= 0)
|
||||||
|
(void) close(fd);
|
||||||
|
if (klen <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (klen <= gzlen)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (opt->force > 0)
|
||||||
|
return klen;
|
||||||
|
|
||||||
|
// some checks
|
||||||
|
if (fd_pos != file_size)
|
||||||
|
{
|
||||||
|
//printf("fd_pos: %ld, file_size: %ld\n", (long)fd_pos, (long)file_size);
|
||||||
|
throwCantPack("trailing bytes after kernel image; use option `-f' to force packing");
|
||||||
|
}
|
||||||
|
// see /usr/src/linux/arch/i386/kernel/head.S:
|
||||||
|
if (memcmp(ibuf, "\xFC\xB8", 2) != 0)
|
||||||
|
throwCantPack("unrecognized kernel architecture; use option `-f' to force packing");
|
||||||
|
|
||||||
|
// FIXME: more checks for special magic bytes in ibuf ???
|
||||||
|
// FIXME: more checks for kernel architecture ???
|
||||||
|
|
||||||
return klen;
|
return klen;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,19 +213,17 @@ int PackVmlinuzI386::uncompressKernel()
|
|||||||
|
|
||||||
void PackVmlinuzI386::readKernel()
|
void PackVmlinuzI386::readKernel()
|
||||||
{
|
{
|
||||||
int klen = uncompressKernel();
|
int klen = decompressKernel();
|
||||||
if (klen <= 0)
|
if (klen <= 0)
|
||||||
throwCantPack("kernel decompression failed");
|
throwCantPack("kernel decompression failed");
|
||||||
if (klen >= (int) ibuf.getSize())
|
|
||||||
throwCantPack("kernel decompression failed -- too big");
|
|
||||||
|
|
||||||
//OutputFile::dump("kernel.img", ibuf, klen);
|
//OutputFile::dump("kernel.img", ibuf, klen);
|
||||||
|
|
||||||
// copy the setup boot code
|
// copy the setup boot code
|
||||||
setup_buf.alloc(setup_size);
|
setup_buf.alloc(setup_size);
|
||||||
memcpy(setup_buf, obuf, setup_size);
|
memcpy(setup_buf, obuf, setup_size);
|
||||||
|
//OutputFile::dump("setup.img", setup_buf, setup_size);
|
||||||
|
|
||||||
obuf.free();
|
obuf.dealloc();
|
||||||
obuf.allocForCompression(klen);
|
obuf.allocForCompression(klen);
|
||||||
|
|
||||||
ph.u_len = klen;
|
ph.u_len = klen;
|
||||||
@@ -191,21 +261,11 @@ void PackVmlinuzI386::pack(OutputFile *fo)
|
|||||||
readKernel();
|
readKernel();
|
||||||
|
|
||||||
// prepare filter
|
// prepare filter
|
||||||
Filter ft(opt->level);
|
Filter ft(ph.level);
|
||||||
ft.buf_len = ph.u_len;
|
ft.buf_len = ph.u_len;
|
||||||
ft.addvalue = kernel_entry;
|
ft.addvalue = kernel_entry;
|
||||||
// prepare other settings
|
// compress
|
||||||
const unsigned overlap_range = 1 << 20;
|
compressWithFilters(&ft, 1 << 20);
|
||||||
unsigned overlapoh;
|
|
||||||
|
|
||||||
int strategy = -1; // try the first working filter
|
|
||||||
if (opt->filter >= 0 && isValidFilter(opt->filter))
|
|
||||||
// try opt->filter or 0 if that fails
|
|
||||||
strategy = -2;
|
|
||||||
else if (opt->all_filters)
|
|
||||||
// choose best from all available filters
|
|
||||||
strategy = 0;
|
|
||||||
compressWithFilters(&ft, &overlapoh, overlap_range, strategy);
|
|
||||||
|
|
||||||
const unsigned lsize = getLoaderSize();
|
const unsigned lsize = getLoaderSize();
|
||||||
MemBuffer loader(lsize);
|
MemBuffer loader(lsize);
|
||||||
@@ -217,7 +277,7 @@ void PackVmlinuzI386::pack(OutputFile *fo)
|
|||||||
patch_le32(loader, lsize, "KEIP", kernel_entry);
|
patch_le32(loader, lsize, "KEIP", kernel_entry);
|
||||||
patch_le32(loader, lsize, "STAK", stack_during_uncompression);
|
patch_le32(loader, lsize, "STAK", stack_during_uncompression);
|
||||||
|
|
||||||
boot_sect_t *bs = (boot_sect_t *) ((unsigned char *) setup_buf);
|
boot_sect_t * const bs = (boot_sect_t *) ((unsigned char *) setup_buf);
|
||||||
bs->sys_size = ALIGN_UP(lsize + ph.c_len, 16) / 16;
|
bs->sys_size = ALIGN_UP(lsize + ph.c_len, 16) / 16;
|
||||||
|
|
||||||
fo->write(setup_buf, setup_buf.getSize());
|
fo->write(setup_buf, setup_buf.getSize());
|
||||||
@@ -229,6 +289,9 @@ void PackVmlinuzI386::pack(OutputFile *fo)
|
|||||||
printf("%-13s: compressed : %8ld bytes\n", getName(), (long) ph.c_len);
|
printf("%-13s: compressed : %8ld bytes\n", getName(), (long) ph.c_len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// verify
|
||||||
|
verifyOverlappingDecompression();
|
||||||
|
|
||||||
// finally check the compression ratio
|
// finally check the compression ratio
|
||||||
if (!checkFinalCompressionRatio(fo))
|
if (!checkFinalCompressionRatio(fo))
|
||||||
throwNotCompressible();
|
throwNotCompressible();
|
||||||
@@ -268,21 +331,11 @@ void PackBvmlinuzI386::pack(OutputFile *fo)
|
|||||||
readKernel();
|
readKernel();
|
||||||
|
|
||||||
// prepare filter
|
// prepare filter
|
||||||
Filter ft(opt->level);
|
Filter ft(ph.level);
|
||||||
ft.buf_len = ph.u_len;
|
ft.buf_len = ph.u_len;
|
||||||
ft.addvalue = kernel_entry;
|
ft.addvalue = kernel_entry;
|
||||||
// prepare other settings
|
// compress
|
||||||
const unsigned overlap_range = 512;
|
compressWithFilters(&ft, 512);
|
||||||
unsigned overlapoh;
|
|
||||||
|
|
||||||
int strategy = -1; // try the first working filter
|
|
||||||
if (opt->filter >= 0 && isValidFilter(opt->filter))
|
|
||||||
// try opt->filter or 0 if that fails
|
|
||||||
strategy = -2;
|
|
||||||
else if (opt->all_filters)
|
|
||||||
// choose best from all available filters
|
|
||||||
strategy = 0;
|
|
||||||
compressWithFilters(&ft, &overlapoh, overlap_range, 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;
|
||||||
@@ -300,7 +353,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
|
||||||
@@ -316,8 +369,8 @@ void PackBvmlinuzI386::pack(OutputFile *fo)
|
|||||||
patch_le32(loader, e_len, "KEIP", kernel_entry);
|
patch_le32(loader, e_len, "KEIP", kernel_entry);
|
||||||
patch_le32(loader, e_len, "STAK", stack_during_uncompression);
|
patch_le32(loader, e_len, "STAK", stack_during_uncompression);
|
||||||
|
|
||||||
boot_sect_t *bs = (boot_sect_t *) ((unsigned char *) setup_buf);
|
boot_sect_t * const bs = (boot_sect_t *) ((unsigned char *) setup_buf);
|
||||||
bs->sys_size = ALIGN_UP(lsize + clen, 16) / 16;
|
bs->sys_size = (ALIGN_UP(lsize + clen, 16) / 16) & 0xffff;
|
||||||
|
|
||||||
fo->write(setup_buf, setup_buf.getSize());
|
fo->write(setup_buf, setup_buf.getSize());
|
||||||
fo->write(loader, e_len);
|
fo->write(loader, e_len);
|
||||||
@@ -331,7 +384,7 @@ void PackBvmlinuzI386::pack(OutputFile *fo)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
verifyOverlappingDecompression(&obuf, overlapoh);
|
verifyOverlappingDecompression();
|
||||||
|
|
||||||
// finally check the compression ratio
|
// finally check the compression ratio
|
||||||
if (!checkFinalCompressionRatio(fo))
|
if (!checkFinalCompressionRatio(fo))
|
||||||
@@ -352,14 +405,34 @@ int PackVmlinuzI386::canUnpack()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PackVmlinuzI386::unpack(OutputFile *)
|
void PackVmlinuzI386::unpack(OutputFile *fo)
|
||||||
{
|
{
|
||||||
// no uncompression support for this format, so that
|
// no uncompression support for this format, so that
|
||||||
// it is possible to remove the original deflate code (>10KB)
|
// it is possible to remove the original deflate code (>10KB)
|
||||||
|
|
||||||
// FIXME: but we could write the uncompressed "vmlinux" image
|
// FIXME: but we could write the uncompressed "vmlinux" image
|
||||||
|
|
||||||
|
ibuf.alloc(ph.c_len);
|
||||||
|
obuf.allocForUncompression(ph.u_len);
|
||||||
|
|
||||||
|
fi->seek(setup_size + ph.buf_offset + ph.getPackHeaderSize(), SEEK_SET);
|
||||||
|
fi->readx(ibuf, ph.c_len);
|
||||||
|
|
||||||
|
// decompress
|
||||||
|
decompress(ibuf, obuf);
|
||||||
|
|
||||||
|
// unfilter
|
||||||
|
Filter ft(ph.level);
|
||||||
|
ft.init(ph.filter, kernel_entry);
|
||||||
|
ft.cto = (unsigned char) ph.filter_cto;
|
||||||
|
ft.unfilter(obuf, ph.u_len);
|
||||||
|
|
||||||
|
// write decompressed file
|
||||||
|
if (fo)
|
||||||
|
{
|
||||||
throwCantUnpack("build a new kernel instead :-)");
|
throwCantUnpack("build a new kernel instead :-)");
|
||||||
|
//fo->write(obuf, ph.u_len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+35
-7
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -39,10 +39,10 @@ class PackVmlinuzI386 : public Packer
|
|||||||
typedef Packer super;
|
typedef Packer super;
|
||||||
public:
|
public:
|
||||||
PackVmlinuzI386(InputFile *f);
|
PackVmlinuzI386(InputFile *f);
|
||||||
virtual int getVersion() const { return 11; }
|
virtual int getVersion() const { return 13; }
|
||||||
virtual int getFormat() const { return UPX_F_VMLINUZ_i386; }
|
virtual int getFormat() const { return UPX_F_VMLINUZ_i386; }
|
||||||
virtual const char *getName() const { return "vmlinuz/386"; }
|
virtual const char *getName() const { return "vmlinuz/386"; }
|
||||||
virtual int getCompressionMethod() const;
|
virtual const int *getCompressionMethods(int method, int level) const;
|
||||||
virtual const int *getFilters() const;
|
virtual const int *getFilters() const;
|
||||||
|
|
||||||
virtual void pack(OutputFile *fo);
|
virtual void pack(OutputFile *fo);
|
||||||
@@ -53,7 +53,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual int readFileHeader();
|
virtual int readFileHeader();
|
||||||
virtual int uncompressKernel();
|
virtual int decompressKernel();
|
||||||
virtual void readKernel();
|
virtual void readKernel();
|
||||||
|
|
||||||
virtual int buildLoader(const Filter *ft);
|
virtual int buildLoader(const Filter *ft);
|
||||||
@@ -79,7 +79,8 @@ protected:
|
|||||||
|
|
||||||
// some more uninteresting fields here ...
|
// some more uninteresting fields here ...
|
||||||
// see /usr/src/linux/Documentation/i386/zero-page.txt
|
// see /usr/src/linux/Documentation/i386/zero-page.txt
|
||||||
};
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
MemBuffer setup_buf;
|
MemBuffer setup_buf;
|
||||||
int setup_size;
|
int setup_size;
|
||||||
@@ -105,6 +106,33 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// elks/8086 (linux-8086 uncompressed kernel image)
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
class PackElks8086 : public PackVmlinuzI386
|
||||||
|
{
|
||||||
|
typedef PackVmlinuzI386 super;
|
||||||
|
public:
|
||||||
|
PackElks8086(InputFile *f) : super(f) { }
|
||||||
|
virtual int getFormat() const { return UPX_F_ELKS_8086; }
|
||||||
|
virtual const char *getName() const { return "elks/8086"; }
|
||||||
|
virtual const int *getCompressionMethods(int method, int level) const;
|
||||||
|
virtual const int *getFilters() const;
|
||||||
|
|
||||||
|
virtual void pack(OutputFile *fo);
|
||||||
|
virtual void unpack(OutputFile *fo);
|
||||||
|
|
||||||
|
virtual int canUnpack();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual int decompressKernel();
|
||||||
|
virtual void readKernel();
|
||||||
|
|
||||||
|
virtual int buildLoader(const Filter *ft);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* already included */
|
#endif /* already included */
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -40,10 +40,10 @@ class PackVxd : public PackWcle
|
|||||||
public:
|
public:
|
||||||
PackVxd(InputFile *f);
|
PackVxd(InputFile *f);
|
||||||
~PackVxd();
|
~PackVxd();
|
||||||
virtual int getVersion() const { return 11; }
|
virtual int getVersion() const { return 13; }
|
||||||
virtual int getFormat() const { return UPX_F_VXD_LE; }
|
virtual int getFormat() const { return UPX_F_VXD_LE; }
|
||||||
virtual const char *getName() const { return "vxd/le"; }
|
virtual const char *getName() const { return "vxd/le"; }
|
||||||
virtual int getCompressionMethod() const;
|
virtual const int *getCompressionMethods(int method, int level) const;
|
||||||
virtual const int *getFilters() const;
|
virtual const int *getFilters() const;
|
||||||
|
|
||||||
virtual void pack(OutputFile *fo);
|
virtual void pack(OutputFile *fo);
|
||||||
|
|||||||
+131
@@ -0,0 +1,131 @@
|
|||||||
|
/* p_w16ne.cpp --
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "conf.h"
|
||||||
|
#include "file.h"
|
||||||
|
#include "filter.h"
|
||||||
|
#include "packer.h"
|
||||||
|
#include "p_w16ne.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
PackW16Ne::PackW16Ne(InputFile *f) :
|
||||||
|
super(f)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const int *PackW16Ne::getCompressionMethods(int method, int level) const
|
||||||
|
{
|
||||||
|
bool small = false;
|
||||||
|
return Packer::getDefaultCompressionMethods_8(method, level, small);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const int *PackW16Ne::getFilters() const
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int PackW16Ne::buildLoader(const Filter *ft)
|
||||||
|
{
|
||||||
|
// prepare loader
|
||||||
|
// initLoader(nrv_loader,sizeof(nrv_loader));
|
||||||
|
// addLoader("...");
|
||||||
|
if (ft->id)
|
||||||
|
{
|
||||||
|
assert(ft->calls > 0);
|
||||||
|
// addLoader("...");
|
||||||
|
}
|
||||||
|
//
|
||||||
|
return getLoaderSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
int PackW16Ne::readFileHeader()
|
||||||
|
{
|
||||||
|
// FIXME: identify a win16/ne executable, so that the call
|
||||||
|
// for contribution below will get thrown
|
||||||
|
return 0;
|
||||||
|
//return UPX_F_WIN16_NE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PackW16Ne::canPack()
|
||||||
|
{
|
||||||
|
if (!readFileHeader())
|
||||||
|
return false;
|
||||||
|
throwCantPack("win16/ne is not supported yet; your contribution is welcome");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
void PackW16Ne::pack(OutputFile *)
|
||||||
|
{
|
||||||
|
throwCantPack("not yet implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
int PackW16Ne::canUnpack()
|
||||||
|
{
|
||||||
|
if (!readFileHeader())
|
||||||
|
return false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
void PackW16Ne::unpack(OutputFile *)
|
||||||
|
{
|
||||||
|
throwCantUnpack("not yet implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
vi:ts=4:et
|
||||||
|
*/
|
||||||
|
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
/* p_w16ne.h --
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __UPX_P_W16NE_H
|
||||||
|
#define __UPX_P_W16NE_H
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// win16/ne
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
class PackW16Ne : public Packer
|
||||||
|
{
|
||||||
|
typedef Packer super;
|
||||||
|
public:
|
||||||
|
PackW16Ne(InputFile *f);
|
||||||
|
virtual int getVersion() const { return 13; }
|
||||||
|
virtual int getFormat() const { return UPX_F_WIN16_NE; }
|
||||||
|
virtual const char *getName() const { return "win16/ne"; }
|
||||||
|
virtual const int *getCompressionMethods(int method, int level) const;
|
||||||
|
virtual const int *getFilters() const;
|
||||||
|
|
||||||
|
virtual void pack(OutputFile *fo);
|
||||||
|
virtual void unpack(OutputFile *fo);
|
||||||
|
|
||||||
|
virtual bool canPack();
|
||||||
|
virtual int canUnpack();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual int readFileHeader(void);
|
||||||
|
|
||||||
|
virtual int buildLoader(const Filter *ft);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* already included */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
vi:ts=4:et
|
||||||
|
*/
|
||||||
|
|
||||||
+236
-148
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -45,15 +45,37 @@ static const
|
|||||||
#define FILLVAL 0
|
#define FILLVAL 0
|
||||||
|
|
||||||
|
|
||||||
// keep the namespace clean
|
// Some defines to keep the namespace clean.
|
||||||
// it would be better to use inner classes except for Interval, which
|
// It would be better to use inner classes except for Interval, which
|
||||||
// could be used elsewhere too
|
// could be used elsewhere too.
|
||||||
|
|
||||||
#define Interval PackW32Pe_Interval
|
#define Interval PackW32Pe_Interval
|
||||||
#define Reloc PackW32Pe_Reloc
|
#define Reloc PackW32Pe_Reloc
|
||||||
#define Resource PackW32Pe_Resource
|
#define Resource PackW32Pe_Resource
|
||||||
#define import_desc PackW32Pe_import_desc
|
#define import_desc PackW32Pe_import_desc
|
||||||
#define Export PackW32Pe_Export
|
#define Export PackW32Pe_Export
|
||||||
|
#define tls PackW32Pe_tls
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#if defined(__BORLANDC__)
|
||||||
|
# undef strcpy
|
||||||
|
# define strcpy(a,b) std::strcpy((char *)(a),(const char *)(b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Unicode string compare
|
||||||
|
static bool ustrsame(const void *s1, const void *s2)
|
||||||
|
{
|
||||||
|
unsigned len1 = get_le16(s1);
|
||||||
|
unsigned len2 = get_le16(s2);
|
||||||
|
if (len1 != len2)
|
||||||
|
return false;
|
||||||
|
return memcmp(s1, s2, 2 + 2*len1) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
@@ -64,17 +86,18 @@ PackW32Pe::PackW32Pe(InputFile *f) : super(f)
|
|||||||
{
|
{
|
||||||
//printf("pe_header_t %d\n", (int) sizeof(pe_header_t));
|
//printf("pe_header_t %d\n", (int) sizeof(pe_header_t));
|
||||||
//printf("pe_section_t %d\n", (int) sizeof(pe_section_t));
|
//printf("pe_section_t %d\n", (int) sizeof(pe_section_t));
|
||||||
assert(sizeof(pe_header_t) == 248);
|
COMPILE_TIME_ASSERT(sizeof(pe_header_t) == 248);
|
||||||
assert(sizeof(pe_section_t) == 40);
|
COMPILE_TIME_ASSERT(sizeof(pe_section_t) == 40);
|
||||||
|
COMPILE_TIME_ASSERT(RT_LAST == HIGH(opt->w32pe.compress_rt));
|
||||||
|
|
||||||
isection = 0;
|
isection = NULL;
|
||||||
oimport = 0;
|
oimport = NULL;
|
||||||
oimpdlls = 0;
|
oimpdlls = NULL;
|
||||||
orelocs = 0;
|
orelocs = NULL;
|
||||||
oexport = 0;
|
oexport = NULL;
|
||||||
otls = 0;
|
otls = NULL;
|
||||||
oresources = 0;
|
oresources = NULL;
|
||||||
oxrelocs = 0;
|
oxrelocs = NULL;
|
||||||
icondir_offset = 0;
|
icondir_offset = 0;
|
||||||
icondir_count = 0;
|
icondir_count = 0;
|
||||||
importbyordinal = false;
|
importbyordinal = false;
|
||||||
@@ -98,20 +121,18 @@ PackW32Pe::~PackW32Pe()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int PackW32Pe::getCompressionMethod() const
|
const int *PackW32Pe::getCompressionMethods(int method, int level) const
|
||||||
{
|
{
|
||||||
if (M_IS_NRV2B(opt->method))
|
bool small = ih.codesize + ih.datasize <= 256*1024;
|
||||||
return M_NRV2B_LE32;
|
return Packer::getDefaultCompressionMethods_le32(method, level, small);
|
||||||
if (M_IS_NRV2D(opt->method))
|
|
||||||
return M_NRV2D_LE32;
|
|
||||||
return opt->level > 1 && file_size >= 512*1024 ? M_NRV2D_LE32 : M_NRV2B_LE32;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const int *PackW32Pe::getFilters() const
|
const int *PackW32Pe::getFilters() const
|
||||||
{
|
{
|
||||||
static const int filters[] = { 0x26, 0x24, 0x16, 0x13, 0x14, 0x11,
|
static const int filters[] = {
|
||||||
0x25, 0x15, 0x12, -1 };
|
0x26, 0x24, 0x16, 0x13, 0x14, 0x11, 0x25, 0x15, 0x12,
|
||||||
|
-1 };
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,9 +151,9 @@ bool PackW32Pe::testUnpackVersion(int version) const
|
|||||||
// util
|
// util
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
bool PackW32Pe::readFileHeader()
|
int PackW32Pe::readFileHeader()
|
||||||
{
|
{
|
||||||
struct h_t
|
struct exe_header_t
|
||||||
{
|
{
|
||||||
LE16 mz;
|
LE16 mz;
|
||||||
LE16 m512;
|
LE16 m512;
|
||||||
@@ -141,8 +162,11 @@ bool PackW32Pe::readFileHeader()
|
|||||||
LE16 relocoffs;
|
LE16 relocoffs;
|
||||||
char __[34];
|
char __[34];
|
||||||
LE32 nexepos;
|
LE32 nexepos;
|
||||||
} h;
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(exe_header_t) == 64);
|
||||||
|
|
||||||
|
exe_header_t h;
|
||||||
int ic;
|
int ic;
|
||||||
pe_offset = 0;
|
pe_offset = 0;
|
||||||
|
|
||||||
@@ -161,16 +185,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -200,7 +224,7 @@ public:
|
|||||||
void flatten();
|
void flatten();
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
void dump();
|
void dump() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static int compare(const void *p1,const void *p2)
|
static int compare(const void *p1,const void *p2)
|
||||||
@@ -254,9 +278,8 @@ void Interval::clear()
|
|||||||
memset((char*) base + ivarr[ic].start,0,ivarr[ic].len);
|
memset((char*) base + ivarr[ic].start,0,ivarr[ic].len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interval::dump()
|
void Interval::dump() const
|
||||||
{
|
{
|
||||||
flatten();
|
|
||||||
printf("%d intervals:\n",ivnum);
|
printf("%d intervals:\n",ivnum);
|
||||||
for (unsigned ic = 0; ic < ivnum; ic++)
|
for (unsigned ic = 0; ic < ivnum; ic++)
|
||||||
printf("%x %x\n",ivarr[ic].start,ivarr[ic].len);
|
printf("%x %x\n",ivarr[ic].start,ivarr[ic].len);
|
||||||
@@ -276,10 +299,17 @@ class Reloc
|
|||||||
{
|
{
|
||||||
LE32 pagestart;
|
LE32 pagestart;
|
||||||
LE32 size;
|
LE32 size;
|
||||||
} *rel;
|
}
|
||||||
LE16 *rel1;
|
__attribute_packed;
|
||||||
void newRelocPos(void *p) { rel = (reloc*) p; rel1 = (LE16*) ((char*) p + sizeof (reloc)); }
|
|
||||||
|
|
||||||
|
void newRelocPos(void *p)
|
||||||
|
{
|
||||||
|
rel = (reloc*) p;
|
||||||
|
rel1 = (LE16*) ((char*) p + sizeof (reloc));
|
||||||
|
}
|
||||||
|
|
||||||
|
reloc *rel;
|
||||||
|
LE16 *rel1;
|
||||||
unsigned counts[16];
|
unsigned counts[16];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -293,15 +323,18 @@ public:
|
|||||||
void finish(upx_byte *&p,unsigned &size);
|
void finish(upx_byte *&p,unsigned &size);
|
||||||
};
|
};
|
||||||
|
|
||||||
Reloc::Reloc(upx_byte *s,unsigned si) : start(s), size(si), rel(0)
|
Reloc::Reloc(upx_byte *s,unsigned si) :
|
||||||
|
start(s), size(si), rel(NULL), rel1(NULL)
|
||||||
{
|
{
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(reloc) == 8);
|
||||||
memset(counts,0,sizeof(counts));
|
memset(counts,0,sizeof(counts));
|
||||||
unsigned pos,type;
|
unsigned pos,type;
|
||||||
while (next(pos,type))
|
while (next(pos,type))
|
||||||
counts[type]++;
|
counts[type]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Reloc::Reloc(unsigned rnum) : rel(0)
|
Reloc::Reloc(unsigned rnum) :
|
||||||
|
start(NULL), size(0), rel(NULL), rel1(NULL)
|
||||||
{
|
{
|
||||||
start = new upx_byte[rnum * 4 + 8192];
|
start = new upx_byte[rnum * 4 + 8192];
|
||||||
counts[0] = 0;
|
counts[0] = 0;
|
||||||
@@ -343,15 +376,14 @@ void Reloc::finish(upx_byte *&p,unsigned &siz)
|
|||||||
prev = pos;
|
prev = pos;
|
||||||
*rel1 = 0;
|
*rel1 = 0;
|
||||||
rel->size = ALIGN_UP(ptr_diff(rel1,rel),4);
|
rel->size = ALIGN_UP(ptr_diff(rel1,rel),4);
|
||||||
newRelocPos(rel->size + (char*) rel);
|
newRelocPos((char *)rel + rel->size);
|
||||||
rel->pagestart = (pos >> 4) &~ 0xfff;
|
rel->pagestart = (pos >> 4) &~ 0xfff;
|
||||||
}
|
}
|
||||||
*rel1++ = (pos << 12) + ((pos >> 4) & 0xfff);
|
*rel1++ = (pos << 12) + ((pos >> 4) & 0xfff);
|
||||||
}
|
}
|
||||||
p = start;
|
p = start;
|
||||||
siz = ptr_diff(rel1,start) &~ 3;
|
siz = ptr_diff(rel1,start) &~ 3;
|
||||||
siz -= 4;
|
siz -= 8;
|
||||||
rel->pagestart = 0; // terminating 0
|
|
||||||
assert(siz > 0);
|
assert(siz > 0);
|
||||||
start = 0; // safety
|
start = 0; // safety
|
||||||
}
|
}
|
||||||
@@ -434,10 +466,13 @@ struct import_desc
|
|||||||
char _[8];
|
char _[8];
|
||||||
LE32 dllname;
|
LE32 dllname;
|
||||||
LE32 iat; // import address table
|
LE32 iat; // import address table
|
||||||
};
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
void PackW32Pe::processImports(unsigned myimport) // pass 2
|
void PackW32Pe::processImports(unsigned myimport) // pass 2
|
||||||
{
|
{
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(import_desc) == 20);
|
||||||
|
|
||||||
// adjust import data
|
// adjust import data
|
||||||
for (import_desc *im = (import_desc*) oimpdlls; im->dllname; im++)
|
for (import_desc *im = (import_desc*) oimpdlls; im->dllname; im++)
|
||||||
{
|
{
|
||||||
@@ -493,11 +528,12 @@ unsigned PackW32Pe::processImports() // pass 1
|
|||||||
if (!u2->shname) return -1;
|
if (!u2->shname) return -1;
|
||||||
return strlen(u1->shname) - strlen(u2->shname);
|
return strlen(u1->shname) - strlen(u2->shname);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
// +1 for dllnum=0
|
// +1 for dllnum=0
|
||||||
autoheap_array(struct udll, dlls, dllnum+1);
|
Array(struct udll, dlls, dllnum+1);
|
||||||
autoheap_array(struct udll *, idlls, dllnum+1);
|
Array(struct udll *, idlls, dllnum+1);
|
||||||
|
|
||||||
soimport = 1024; // safety
|
soimport = 1024; // safety
|
||||||
|
|
||||||
@@ -679,14 +715,16 @@ unsigned PackW32Pe::processImports() // pass 1
|
|||||||
// This decreases compression ratio, so FIXME somehow.
|
// This decreases compression ratio, so FIXME somehow.
|
||||||
infoWarning("can't remove unneeded imports");
|
infoWarning("can't remove unneeded imports");
|
||||||
ilen += sizeof(import_desc) * dllnum;
|
ilen += sizeof(import_desc) * dllnum;
|
||||||
|
#if defined(DEBUG)
|
||||||
if (opt->verbose > 3)
|
if (opt->verbose > 3)
|
||||||
names.dump();
|
names.dump();
|
||||||
|
#endif
|
||||||
// do some work for the unpacker
|
// do some work for the unpacker
|
||||||
im = im_save;
|
im = im_save;
|
||||||
for (ic = 0; ic < dllnum; ic++)
|
for (ic = 0; ic < dllnum; ic++, im++)
|
||||||
{
|
{
|
||||||
memset(im,FILLVAL,sizeof(*im));
|
memset(im,FILLVAL,sizeof(*im));
|
||||||
im++->dllname = ptr_diff(idlls[ic]->name,ibuf); // I only need this info
|
im->dllname = ptr_diff(idlls[ic]->name,ibuf); // I only need this info
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -715,7 +753,7 @@ unsigned PackW32Pe::processImports() // pass 1
|
|||||||
|
|
||||||
class Export
|
class Export
|
||||||
{
|
{
|
||||||
struct export_dir
|
struct export_dir_t
|
||||||
{
|
{
|
||||||
char _[12]; // flags, timedate, version
|
char _[12]; // flags, timedate, version
|
||||||
LE32 name;
|
LE32 name;
|
||||||
@@ -725,9 +763,10 @@ class Export
|
|||||||
LE32 addrtable;
|
LE32 addrtable;
|
||||||
LE32 nameptrtable;
|
LE32 nameptrtable;
|
||||||
LE32 ordinaltable;
|
LE32 ordinaltable;
|
||||||
};
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
export_dir edir;
|
export_dir_t edir;
|
||||||
char *ename;
|
char *ename;
|
||||||
char *functionptrs;
|
char *functionptrs;
|
||||||
char *ordinals;
|
char *ordinals;
|
||||||
@@ -752,8 +791,9 @@ private:
|
|||||||
|
|
||||||
Export::Export(char *_base) : base(_base), iv(_base)
|
Export::Export(char *_base) : base(_base), iv(_base)
|
||||||
{
|
{
|
||||||
ename = functionptrs = ordinals = 0;
|
COMPILE_TIME_ASSERT(sizeof(export_dir_t) == 40);
|
||||||
names = 0;
|
ename = functionptrs = ordinals = NULL;
|
||||||
|
names = NULL;
|
||||||
memset(&edir,0,sizeof(edir));
|
memset(&edir,0,sizeof(edir));
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
@@ -770,8 +810,8 @@ Export::~Export()
|
|||||||
|
|
||||||
void Export::convert(unsigned eoffs,unsigned esize)
|
void Export::convert(unsigned eoffs,unsigned esize)
|
||||||
{
|
{
|
||||||
memcpy(&edir,base + eoffs,sizeof(export_dir));
|
memcpy(&edir,base + eoffs,sizeof(export_dir_t));
|
||||||
size = sizeof(export_dir);
|
size = sizeof(export_dir_t);
|
||||||
iv.add(eoffs,size);
|
iv.add(eoffs,size);
|
||||||
|
|
||||||
unsigned len = strlen(base + edir.name) + 1;
|
unsigned len = strlen(base + edir.name) + 1;
|
||||||
@@ -820,8 +860,10 @@ void Export::convert(unsigned eoffs,unsigned esize)
|
|||||||
iv.flatten();
|
iv.flatten();
|
||||||
if (iv.ivnum == 1)
|
if (iv.ivnum == 1)
|
||||||
iv.clear();
|
iv.clear();
|
||||||
|
#if defined(DEBUG)
|
||||||
else
|
else
|
||||||
iv.dump();
|
iv.dump();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Export::build(char *newbase,unsigned newoffs)
|
void Export::build(char *newbase,unsigned newoffs)
|
||||||
@@ -904,16 +946,34 @@ struct tls
|
|||||||
LE32 tlsindex; // VA tls index
|
LE32 tlsindex; // VA tls index
|
||||||
LE32 callbacks; // VA tls callbacks
|
LE32 callbacks; // VA tls callbacks
|
||||||
char _[8]; // zero init, characteristics
|
char _[8]; // zero init, characteristics
|
||||||
};
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
void PackW32Pe::processTls(Interval *iv) // pass 1
|
void PackW32Pe::processTls(Interval *iv) // pass 1
|
||||||
{
|
{
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(tls) == 24);
|
||||||
|
|
||||||
if ((sotls = ALIGN_UP(IDSIZE(PEDIR_TLS),4)) == 0)
|
if ((sotls = ALIGN_UP(IDSIZE(PEDIR_TLS),4)) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const tls * const tlsp = (const tls*) (ibuf + IDADDR(PEDIR_TLS));
|
const tls * const tlsp = (const tls*) (ibuf + IDADDR(PEDIR_TLS));
|
||||||
unsigned tlsdatastart = tlsp->datastart - ih.imagebase;
|
// note: TLS callbacks are not implemented in Windows 95/98/ME
|
||||||
unsigned tlsdataend = tlsp->dataend - ih.imagebase;
|
if (tlsp->callbacks)
|
||||||
|
{
|
||||||
|
if (tlsp->callbacks < ih.imagebase)
|
||||||
|
throwCantPack("invalid TLS callback");
|
||||||
|
else if (tlsp->callbacks - ih.imagebase + 4 >= ih.imagesize)
|
||||||
|
throwCantPack("invalid TLS callback");
|
||||||
|
unsigned v = get_le32(ibuf + tlsp->callbacks - ih.imagebase);
|
||||||
|
if (v != 0)
|
||||||
|
{
|
||||||
|
//fprintf(stderr, "TLS callbacks: 0x%0x -> 0x%0x\n", (int)tlsp->callbacks, v);
|
||||||
|
throwCantPack("TLS callbacks are not supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned tlsdatastart = tlsp->datastart - ih.imagebase;
|
||||||
|
const unsigned tlsdataend = tlsp->dataend - ih.imagebase;
|
||||||
|
|
||||||
// now some ugly stuff: find the relocation entries in the tls data area
|
// now some ugly stuff: find the relocation entries in the tls data area
|
||||||
unsigned pos,type;
|
unsigned pos,type;
|
||||||
@@ -961,7 +1021,7 @@ void PackW32Pe::processTls(Reloc *rel,const Interval *iv,unsigned newaddr) // pa
|
|||||||
|
|
||||||
tlsp->datastart = newaddr + sizeof(tls) + ih.imagebase;
|
tlsp->datastart = newaddr + sizeof(tls) + ih.imagebase;
|
||||||
tlsp->dataend = newaddr + sotls + ih.imagebase;
|
tlsp->dataend = newaddr + sotls + ih.imagebase;
|
||||||
tlsp->callbacks = 0; // note: callbacks are not implemented in windoze
|
tlsp->callbacks = 0; // note: TLS callbacks are not implemented in Windows 95/98/ME
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -975,7 +1035,8 @@ class Resource
|
|||||||
{
|
{
|
||||||
LE32 tnl; // Type | Name | Language id - depending on level
|
LE32 tnl; // Type | Name | Language id - depending on level
|
||||||
LE32 child;
|
LE32 child;
|
||||||
};
|
}
|
||||||
|
__attribute_packed;
|
||||||
struct res_dir
|
struct res_dir
|
||||||
{
|
{
|
||||||
char _[12]; // flags, timedate, version
|
char _[12]; // flags, timedate, version
|
||||||
@@ -986,13 +1047,15 @@ class Resource
|
|||||||
res_dir_entry entries[1];
|
res_dir_entry entries[1];
|
||||||
// it's usually safe to assume that every res_dir contains
|
// it's usually safe to assume that every res_dir contains
|
||||||
// at least one res_dir_entry - check() complains otherwise
|
// at least one res_dir_entry - check() complains otherwise
|
||||||
};
|
}
|
||||||
|
__attribute_packed;
|
||||||
struct res_data
|
struct res_data
|
||||||
{
|
{
|
||||||
LE32 offset;
|
LE32 offset;
|
||||||
LE32 size;
|
LE32 size;
|
||||||
char _[8]; // codepage, reserved
|
char _[8]; // codepage, reserved
|
||||||
};
|
}
|
||||||
|
__attribute_packed;
|
||||||
//
|
//
|
||||||
struct upx_rnode
|
struct upx_rnode
|
||||||
{
|
{
|
||||||
@@ -1029,7 +1092,7 @@ class Resource
|
|||||||
void destroy(upx_rnode *urd,unsigned level);
|
void destroy(upx_rnode *urd,unsigned level);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Resource() : root(0) {}
|
Resource() : root(NULL) {}
|
||||||
Resource(const upx_byte *p) {init(p);}
|
Resource(const upx_byte *p) {init(p);}
|
||||||
~Resource() {if (root) destroy (root,0);}
|
~Resource() {if (root) destroy (root,0);}
|
||||||
void init(const upx_byte *);
|
void init(const upx_byte *);
|
||||||
@@ -1058,6 +1121,10 @@ public:
|
|||||||
|
|
||||||
void Resource::init(const upx_byte *res)
|
void Resource::init(const upx_byte *res)
|
||||||
{
|
{
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(res_dir_entry) == 8);
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(res_dir) == 16 + sizeof(res_dir_entry));
|
||||||
|
COMPILE_TIME_ASSERT(sizeof(res_data) == 16);
|
||||||
|
|
||||||
start = res;
|
start = res;
|
||||||
root = head = current = 0;
|
root = head = current = 0;
|
||||||
dsize = ssize = 0;
|
dsize = ssize = 0;
|
||||||
@@ -1069,7 +1136,10 @@ void Resource::check(const res_dir *node,unsigned level)
|
|||||||
{
|
{
|
||||||
int ic = node->identr + node->namedentr;
|
int ic = node->identr + node->namedentr;
|
||||||
if (ic == 0)
|
if (ic == 0)
|
||||||
throwCantPack("unsupported resource structure");
|
{
|
||||||
|
//throwCantPack("unsupported resource structure");
|
||||||
|
throwCantPack("empty resource sections are not supported");
|
||||||
|
}
|
||||||
for (const res_dir_entry *rde = node->entries; --ic >= 0; rde++)
|
for (const res_dir_entry *rde = node->entries; --ic >= 0; rde++)
|
||||||
if (((rde->child & 0x80000000) == 0) ^ (level == 2))
|
if (((rde->child & 0x80000000) == 0) ^ (level == 2))
|
||||||
throwCantPack("unsupported resource structure");
|
throwCantPack("unsupported resource structure");
|
||||||
@@ -1164,13 +1234,13 @@ upx_byte *Resource::build()
|
|||||||
|
|
||||||
void Resource::destroy(upx_rnode *node,unsigned level)
|
void Resource::destroy(upx_rnode *node,unsigned level)
|
||||||
{
|
{
|
||||||
delete [] node->name;
|
delete [] node->name; node->name = NULL;
|
||||||
if (level == 3)
|
if (level == 3)
|
||||||
return;
|
return;
|
||||||
const upx_rbranch *branch = (const upx_rbranch*) node;
|
upx_rbranch * const branch = (upx_rbranch *) node;
|
||||||
for (int ic = branch->nc; --ic >= 0; )
|
for (int ic = branch->nc; --ic >= 0; )
|
||||||
destroy(branch->children[ic],level + 1);
|
destroy(branch->children[ic],level + 1);
|
||||||
delete [] branch->children;
|
delete [] branch->children; branch->children = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lame_print_unicode(const upx_byte *p)
|
static void lame_print_unicode(const upx_byte *p)
|
||||||
@@ -1183,16 +1253,17 @@ void Resource::dump(const upx_rnode *node,unsigned level) const
|
|||||||
{
|
{
|
||||||
if (level)
|
if (level)
|
||||||
{
|
{
|
||||||
printf("\t\t\t\t" + 6 - level * 2);
|
for (unsigned ic = 1; ic < level; ic++)
|
||||||
|
printf("\t\t");
|
||||||
if (node->name)
|
if (node->name)
|
||||||
lame_print_unicode(node->name);
|
lame_print_unicode(node->name);
|
||||||
else
|
else
|
||||||
printf("%x",node->id);
|
printf("0x%x",node->id);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
if (level == 3)
|
if (level == 3)
|
||||||
return;
|
return;
|
||||||
const upx_rbranch *branch = (const upx_rbranch*) node;
|
const upx_rbranch * const branch = (const upx_rbranch *) node;
|
||||||
for (unsigned ic = 0; ic < branch->nc; ic++)
|
for (unsigned ic = 0; ic < branch->nc; ic++)
|
||||||
dump(branch->children[ic],level + 1);
|
dump(branch->children[ic],level + 1);
|
||||||
}
|
}
|
||||||
@@ -1204,8 +1275,9 @@ void Resource::clear(upx_byte *node,unsigned level,Interval *iv)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
const res_dir * const rd = (res_dir*) node;
|
const res_dir * const rd = (res_dir*) node;
|
||||||
|
const unsigned n = rd->identr + rd->namedentr;
|
||||||
const res_dir_entry *rde = rd->entries;
|
const res_dir_entry *rde = rd->entries;
|
||||||
for (unsigned ic = 0; ic < rd->identr + rd->namedentr; ic++, rde++)
|
for (unsigned ic = 0; ic < n; ic++, rde++)
|
||||||
clear(newstart + (rde->child & 0x7fffffff),level + 1,iv);
|
clear(newstart + (rde->child & 0x7fffffff),level + 1,iv);
|
||||||
iv->add(rd,rd->Sizeof());
|
iv->add(rd,rd->Sizeof());
|
||||||
}
|
}
|
||||||
@@ -1219,8 +1291,10 @@ bool Resource::clear()
|
|||||||
iv.flatten();
|
iv.flatten();
|
||||||
if (iv.ivnum == 1)
|
if (iv.ivnum == 1)
|
||||||
iv.clear();
|
iv.clear();
|
||||||
|
#if defined(DEBUG)
|
||||||
if (opt->verbose > 3)
|
if (opt->verbose > 3)
|
||||||
iv.dump();
|
iv.dump();
|
||||||
|
#endif
|
||||||
return iv.ivnum == 1;
|
return iv.ivnum == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1241,6 +1315,24 @@ void PackW32Pe::processResources(Resource* res)
|
|||||||
const unsigned vaddr = IDADDR(PEDIR_RESOURCE);
|
const unsigned vaddr = IDADDR(PEDIR_RESOURCE);
|
||||||
if ((soresources = IDSIZE(PEDIR_RESOURCE)) == 0)
|
if ((soresources = IDSIZE(PEDIR_RESOURCE)) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// setup default options for resource compression
|
||||||
|
if (opt->w32pe.compress_resources < 0)
|
||||||
|
opt->w32pe.compress_resources = true;
|
||||||
|
if (!opt->w32pe.compress_resources)
|
||||||
|
{
|
||||||
|
opt->w32pe.compress_icons = false;
|
||||||
|
for (int i = 0; i < RT_LAST; i++)
|
||||||
|
opt->w32pe.compress_rt[i] = false;
|
||||||
|
}
|
||||||
|
if (opt->w32pe.compress_rt[RT_STRING] < 0)
|
||||||
|
{
|
||||||
|
// by default, don't compress RT_STRINGs of screensavers (".scr")
|
||||||
|
opt->w32pe.compress_rt[RT_STRING] = true;
|
||||||
|
if (fn_has_ext(fi->getName(),"scr"))
|
||||||
|
opt->w32pe.compress_rt[RT_STRING] = false;
|
||||||
|
}
|
||||||
|
|
||||||
res->init(ibuf + vaddr);
|
res->init(ibuf + vaddr);
|
||||||
|
|
||||||
for (soresources = res->dirsize(); res->next(); soresources += 4 + res->size())
|
for (soresources = res->dirsize(); res->next(); soresources += 4 + res->size())
|
||||||
@@ -1251,7 +1343,7 @@ void PackW32Pe::processResources(Resource* res)
|
|||||||
unsigned iconsin1stdir = 0;
|
unsigned iconsin1stdir = 0;
|
||||||
if (opt->w32pe.compress_icons == 2)
|
if (opt->w32pe.compress_icons == 2)
|
||||||
while (res->next()) // there is no rewind() in Resource
|
while (res->next()) // there is no rewind() in Resource
|
||||||
if (res->itype() == 14 && iconsin1stdir == 0)
|
if (res->itype() == RT_GROUP_ICON && iconsin1stdir == 0)
|
||||||
iconsin1stdir = get_le16(ibuf + res->offs() + 4);
|
iconsin1stdir = get_le16(ibuf + res->offs() + 4);
|
||||||
|
|
||||||
bool compress_icon = false, compress_idir = false;
|
bool compress_icon = false, compress_idir = false;
|
||||||
@@ -1267,25 +1359,32 @@ void PackW32Pe::processResources(Resource* res)
|
|||||||
{
|
{
|
||||||
const unsigned rtype = res->itype();
|
const unsigned rtype = res->itype();
|
||||||
bool do_compress = true;
|
bool do_compress = true;
|
||||||
if (rtype == 16) // version info
|
|
||||||
do_compress = false;
|
|
||||||
else if (rtype == 3) // icon
|
|
||||||
do_compress = compress_icon && opt->w32pe.compress_icons;
|
|
||||||
else if (rtype == 14) // icon directory
|
|
||||||
do_compress = compress_idir && opt->w32pe.compress_icons;
|
|
||||||
else if (res->ntype()) // named resource type
|
|
||||||
if (0 == memcmp(res->ntype(),"\x7\x0T\x0Y\x0P\x0""E\x0L\x0I\x0""B\x0",16)
|
|
||||||
|| 0 == memcmp(res->ntype(),"\x8\x0R\x0""E\x0G\x0I\x0S\x0T\x0R\x0Y\x0",18))
|
|
||||||
do_compress = false; // typelib or registry
|
|
||||||
|
|
||||||
if (!opt->w32pe.compress_resources)
|
if (!opt->w32pe.compress_resources)
|
||||||
do_compress = false;
|
do_compress = false;
|
||||||
|
else if (rtype == RT_VERSION) // version info
|
||||||
|
do_compress = false;
|
||||||
|
else if (rtype == RT_ICON) // icon
|
||||||
|
do_compress = compress_icon && opt->w32pe.compress_icons;
|
||||||
|
else if (rtype == RT_GROUP_ICON) // icon directory
|
||||||
|
do_compress = compress_idir && opt->w32pe.compress_icons;
|
||||||
|
else if (rtype > 0 && rtype < RT_LAST)
|
||||||
|
do_compress = opt->w32pe.compress_rt[rtype] ? true : false;
|
||||||
|
else if (res->ntype()) // named resource type
|
||||||
|
{
|
||||||
|
const upx_byte * const t = res->ntype();
|
||||||
|
if (ustrsame(t, "\x7\x0T\x0Y\x0P\x0""E\x0L\x0I\x0""B\x0"))
|
||||||
|
do_compress = false; // u"TYPELIB"
|
||||||
|
else if (ustrsame(t, "\x8\x0R\x0""E\x0G\x0I\x0S\x0T\x0R\x0Y\x0"))
|
||||||
|
do_compress = false; // u"REGISTRY"
|
||||||
|
}
|
||||||
|
|
||||||
if (do_compress)
|
if (do_compress)
|
||||||
{
|
{
|
||||||
csize += res->size();
|
csize += res->size();
|
||||||
cnum++;
|
cnum++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
usize += res->size();
|
usize += res->size();
|
||||||
unum++;
|
unum++;
|
||||||
|
|
||||||
@@ -1294,9 +1393,9 @@ void PackW32Pe::processResources(Resource* res)
|
|||||||
memcpy(ores,ibuf + res->offs(),res->size());
|
memcpy(ores,ibuf + res->offs(),res->size());
|
||||||
memset(ibuf + res->offs(),FILLVAL,res->size());
|
memset(ibuf + res->offs(),FILLVAL,res->size());
|
||||||
res->newoffs() = ptr_diff(ores,oresources);
|
res->newoffs() = ptr_diff(ores,oresources);
|
||||||
if (rtype == 3)
|
if (rtype == RT_ICON)
|
||||||
compress_icon = (++iconcnt >= iconsin1stdir || opt->w32pe.compress_icons == 1);
|
compress_icon = (++iconcnt >= iconsin1stdir || opt->w32pe.compress_icons == 1);
|
||||||
else if (rtype == 14)
|
else if (rtype == RT_GROUP_ICON)
|
||||||
{
|
{
|
||||||
if (opt->w32pe.compress_icons == 1)
|
if (opt->w32pe.compress_icons == 1)
|
||||||
{
|
{
|
||||||
@@ -1359,7 +1458,8 @@ unsigned PackW32Pe::stripDebug(unsigned overlaystart)
|
|||||||
LE32 size;
|
LE32 size;
|
||||||
char __[4]; // rva
|
char __[4]; // rva
|
||||||
LE32 fpos;
|
LE32 fpos;
|
||||||
};
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
const debug_dir_t *dd = (const debug_dir_t*) (ibuf + IDADDR(PEDIR_DEBUG));
|
const debug_dir_t *dd = (const debug_dir_t*) (ibuf + IDADDR(PEDIR_DEBUG));
|
||||||
for (unsigned ic = 0; ic < IDSIZE(PEDIR_DEBUG) / sizeof(debug_dir_t); ic++, dd++)
|
for (unsigned ic = 0; ic < IDSIZE(PEDIR_DEBUG) / sizeof(debug_dir_t); ic++, dd++)
|
||||||
@@ -1376,14 +1476,16 @@ unsigned PackW32Pe::stripDebug(unsigned overlaystart)
|
|||||||
|
|
||||||
bool PackW32Pe::canPack()
|
bool PackW32Pe::canPack()
|
||||||
{
|
{
|
||||||
return readFileHeader();
|
if (!readFileHeader())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int PackW32Pe::buildLoader(const Filter *ft)
|
int PackW32Pe::buildLoader(const Filter *ft)
|
||||||
{
|
{
|
||||||
// prepare loader
|
// prepare loader
|
||||||
initLoader(nrv_loader,sizeof(nrv_loader));
|
initLoader(nrv_loader, sizeof(nrv_loader), -1, 2);
|
||||||
addLoader(isdll ? "PEISDLL1" : "",
|
addLoader(isdll ? "PEISDLL1" : "",
|
||||||
"PEMAIN01",
|
"PEMAIN01",
|
||||||
icondir_count > 1 ? (icondir_count == 2 ? "PEICONS1" : "PEICONS2") : "",
|
icondir_count > 1 ? (icondir_count == 2 ? "PEICONS1" : "PEICONS2") : "",
|
||||||
@@ -1488,7 +1590,7 @@ void PackW32Pe::pack(OutputFile *fo)
|
|||||||
throwCantPack("filealign < 0x200 is not yet supported");
|
throwCantPack("filealign < 0x200 is not yet supported");
|
||||||
|
|
||||||
handleStub(fi,fo,pe_offset);
|
handleStub(fi,fo,pe_offset);
|
||||||
unsigned usize = ih.imagesize;
|
const unsigned usize = ih.imagesize;
|
||||||
const unsigned xtrasize = 65536+IDSIZE(PEDIR_IMPORT)+IDSIZE(PEDIR_BOUNDIM)+IDSIZE(PEDIR_IAT)+IDSIZE(PEDIR_DELAYIMP)+IDSIZE(PEDIR_RELOC);
|
const unsigned xtrasize = 65536+IDSIZE(PEDIR_IMPORT)+IDSIZE(PEDIR_BOUNDIM)+IDSIZE(PEDIR_IAT)+IDSIZE(PEDIR_DELAYIMP)+IDSIZE(PEDIR_RELOC);
|
||||||
ibuf.alloc(usize + xtrasize);
|
ibuf.alloc(usize + xtrasize);
|
||||||
|
|
||||||
@@ -1500,7 +1602,7 @@ void PackW32Pe::pack(OutputFile *fo)
|
|||||||
|
|
||||||
unsigned ic,jc,overlaystart = 0;
|
unsigned ic,jc,overlaystart = 0;
|
||||||
memset(ibuf,0,usize);
|
memset(ibuf,0,usize);
|
||||||
for (ic = 0; ic < objs; ic++)
|
for (ic = jc = 0; ic < objs; ic++)
|
||||||
{
|
{
|
||||||
if (isection[ic].rawdataptr && overlaystart < isection[ic].rawdataptr + isection[ic].size)
|
if (isection[ic].rawdataptr && overlaystart < isection[ic].rawdataptr + isection[ic].size)
|
||||||
overlaystart = ALIGN_UP(isection[ic].rawdataptr + isection[ic].size,ih.filealign);
|
overlaystart = ALIGN_UP(isection[ic].rawdataptr + isection[ic].size,ih.filealign);
|
||||||
@@ -1512,23 +1614,26 @@ void PackW32Pe::pack(OutputFile *fo)
|
|||||||
holes.add(isection[ic].vaddr,isection[ic].vsize);
|
holes.add(isection[ic].vaddr,isection[ic].vsize);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!isrtm && ((isection[ic].flags & (PEFL_WRITE|PEFL_SHARED))
|
|
||||||
== (PEFL_WRITE|PEFL_SHARED)) && !opt->force)
|
|
||||||
throwCantPack("writeable shared sections not supported (try --force)");
|
|
||||||
fi->seek(isection[ic].rawdataptr,SEEK_SET);
|
|
||||||
if (isection[ic].vaddr + isection[ic].size > usize)
|
if (isection[ic].vaddr + isection[ic].size > usize)
|
||||||
throwCantPack("section size problem");
|
throwCantPack("section size problem");
|
||||||
|
if (!isrtm && ((isection[ic].flags & (PEFL_WRITE|PEFL_SHARED))
|
||||||
|
== (PEFL_WRITE|PEFL_SHARED)))
|
||||||
|
if (!opt->force)
|
||||||
|
throwCantPack("writeable shared sections not supported (try --force)");
|
||||||
|
if (jc && isection[ic].rawdataptr - jc > ih.filealign)
|
||||||
|
throwCantPack("superfluous data between sections");
|
||||||
|
fi->seek(isection[ic].rawdataptr,SEEK_SET);
|
||||||
jc = isection[ic].size;
|
jc = isection[ic].size;
|
||||||
if (jc > isection[ic].vsize)
|
if (jc > isection[ic].vsize)
|
||||||
jc = isection[ic].vsize;
|
jc = isection[ic].vsize;
|
||||||
if (isection[ic].vsize == 0) // hack for some tricky programs - may this break other progs?
|
if (isection[ic].vsize == 0) // hack for some tricky programs - may this break other progs?
|
||||||
jc = isection[ic].vsize = isection[ic].size;
|
jc = isection[ic].vsize = isection[ic].size;
|
||||||
fi->readx(ibuf + isection[ic].vaddr,jc);
|
fi->readx(ibuf + isection[ic].vaddr,jc);
|
||||||
|
jc += isection[ic].rawdataptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for NeoLite
|
// check for NeoLite
|
||||||
for (ic = 0; ic < 64; ic++)
|
if (find(ibuf + ih.entry, 64+7, "NeoLite", 7) >= 0)
|
||||||
if (memcmp(ibuf + ih.entry + ic,"NeoLite",7) == 0)
|
|
||||||
throwCantPack("file is already compressed with another packer");
|
throwCantPack("file is already compressed with another packer");
|
||||||
|
|
||||||
unsigned overlay = file_size - stripDebug(overlaystart);
|
unsigned overlay = file_size - stripDebug(overlaystart);
|
||||||
@@ -1611,53 +1716,19 @@ void PackW32Pe::pack(OutputFile *fo)
|
|||||||
s += 4;
|
s += 4;
|
||||||
ph.u_len += s;
|
ph.u_len += s;
|
||||||
obuf.allocForCompression(ph.u_len);
|
obuf.allocForCompression(ph.u_len);
|
||||||
ph.u_len -= rvamin;
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
// filter
|
|
||||||
Filter ft(opt->level);
|
|
||||||
if (allow_filter)
|
|
||||||
tryFilters(&ft, ibuf + ih.codebase, ih.codesize);
|
|
||||||
|
|
||||||
// compress
|
|
||||||
ph.filter = ft.id;
|
|
||||||
ph.filter_cto = ft.cto;
|
|
||||||
if (!compress(ibuf + rvamin,obuf))
|
|
||||||
throwNotCompressible();
|
|
||||||
const unsigned overlapoh = findOverlapOverhead(obuf, 2048);
|
|
||||||
|
|
||||||
// verify filter
|
|
||||||
ft.verifyUnfilter();
|
|
||||||
buildLoader(&ft);
|
|
||||||
#else
|
|
||||||
// new version using compressWithFilters()
|
|
||||||
// FIXME - this does not work yet !!!
|
|
||||||
|
|
||||||
// prepare packheader
|
// prepare packheader
|
||||||
ph.filter = 0;
|
ph.u_len -= rvamin;
|
||||||
// prepare filter
|
// prepare filter
|
||||||
Filter ft(opt->level);
|
Filter ft(ph.level);
|
||||||
ft.buf_len = ih.codesize;
|
ft.buf_len = ih.codesize;
|
||||||
ft.addvalue = 0;
|
ft.addvalue = ih.codebase - rvamin;
|
||||||
// prepare other settings
|
// compress
|
||||||
const unsigned overlap_range = 2048;
|
int strategy = allow_filter ? 0 : -3;
|
||||||
unsigned overlapoh;
|
compressWithFilters(&ft, 2048, strategy,
|
||||||
|
|
||||||
int strategy = -1; // try the first working filter
|
|
||||||
if (!allow_filter)
|
|
||||||
// no filter
|
|
||||||
strategy = -3;
|
|
||||||
else if (opt->filter >= 0 && isValidFilter(opt->filter))
|
|
||||||
// try opt->filter or 0 if that fails
|
|
||||||
strategy = -2;
|
|
||||||
else if (opt->all_filters)
|
|
||||||
// choose best from all available filters
|
|
||||||
strategy = 0;
|
|
||||||
compressWithFilters(&ft, &overlapoh, overlap_range, strategy,
|
|
||||||
NULL, 0, 0, ih.codebase, rvamin);
|
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)
|
if (tlsindex && ((newvsize - ph.c_len - 1024 + oam1) &~ oam1) > tlsindex + 4)
|
||||||
tlsindex = 0;
|
tlsindex = 0;
|
||||||
|
|
||||||
@@ -1805,10 +1876,15 @@ void PackW32Pe::pack(OutputFile *fo)
|
|||||||
ODSIZE(PEDIR_RELOC) = soxrelocs;
|
ODSIZE(PEDIR_RELOC) = soxrelocs;
|
||||||
ic += soxrelocs;
|
ic += soxrelocs;
|
||||||
|
|
||||||
// this is here, because soxrelocs changes some lines above
|
// this is computed here, because soxrelocs changes some lines above
|
||||||
const unsigned ncsize = soresources + soimpdlls + soexport + soxrelocs;
|
const unsigned ncsize = soresources + soimpdlls + soexport + soxrelocs;
|
||||||
ic = oh.filealign - 1;
|
ic = oh.filealign - 1;
|
||||||
|
|
||||||
|
// this one is tricky: it seems windoze touches 4 bytes after
|
||||||
|
// the end of the relocation data - so we have to increase
|
||||||
|
// the virtual size of this section
|
||||||
|
const unsigned ncsize_virt_increase = (ncsize & oam1) == 0 ? 8 : 0;
|
||||||
|
|
||||||
// fill the sections
|
// fill the sections
|
||||||
strcpy(osection[0].name,"UPX0");
|
strcpy(osection[0].name,"UPX0");
|
||||||
strcpy(osection[1].name,"UPX1");
|
strcpy(osection[1].name,"UPX1");
|
||||||
@@ -1832,7 +1908,7 @@ void PackW32Pe::pack(OutputFile *fo)
|
|||||||
|
|
||||||
osection[0].vsize = osection[1].vaddr - osection[0].vaddr;
|
osection[0].vsize = osection[1].vaddr - osection[0].vaddr;
|
||||||
osection[1].vsize = (osection[1].size + oam1) &~ oam1;
|
osection[1].vsize = (osection[1].size + oam1) &~ oam1;
|
||||||
osection[2].vsize = (osection[2].size + oam1) &~ oam1;
|
osection[2].vsize = (osection[2].size + ncsize_virt_increase + oam1) &~ oam1;
|
||||||
|
|
||||||
osection[0].rawdataptr = (pe_offset + sizeof(oh) + sizeof(osection) + ic) &~ ic;
|
osection[0].rawdataptr = (pe_offset + sizeof(oh) + sizeof(osection) + ic) &~ ic;
|
||||||
osection[1].rawdataptr = osection[0].rawdataptr;
|
osection[1].rawdataptr = osection[0].rawdataptr;
|
||||||
@@ -1848,13 +1924,15 @@ void PackW32Pe::pack(OutputFile *fo)
|
|||||||
oh.database = osection[2].vaddr;
|
oh.database = osection[2].vaddr;
|
||||||
oh.codesize = osection[1].vsize;
|
oh.codesize = osection[1].vsize;
|
||||||
oh.codebase = osection[1].vaddr;
|
oh.codebase = osection[1].vaddr;
|
||||||
oh.headersize = osection[0].rawdataptr;
|
// oh.headersize = osection[0].rawdataptr;
|
||||||
|
oh.headersize = rvamin;
|
||||||
|
|
||||||
if (opt->w32pe.strip_relocs && !isdll)
|
if (opt->w32pe.strip_relocs && !isdll)
|
||||||
oh.flags |= RELOCS_STRIPPED;
|
oh.flags |= RELOCS_STRIPPED;
|
||||||
|
|
||||||
//for (ic = 0; ic < oh.filealign; ic += 4)
|
//for (ic = 0; ic < oh.filealign; ic += 4)
|
||||||
// set_le32(ibuf + ic,get_le32("UPX "));
|
// set_le32(ibuf + ic,get_le32("UPX "));
|
||||||
|
assert(oh.filealign <= ibuf.getSize());
|
||||||
memset(ibuf,0,oh.filealign);
|
memset(ibuf,0,oh.filealign);
|
||||||
|
|
||||||
infoHeader("[Writing compressed file]");
|
infoHeader("[Writing compressed file]");
|
||||||
@@ -1864,7 +1942,11 @@ void PackW32Pe::pack(OutputFile *fo)
|
|||||||
fo->write(osection,sizeof(osection));
|
fo->write(osection,sizeof(osection));
|
||||||
// some alignment
|
// some alignment
|
||||||
if (identsplit == identsize)
|
if (identsplit == identsize)
|
||||||
fo->write(ibuf,osection[0].rawdataptr - fo->getBytesWritten() - identsize);
|
{
|
||||||
|
unsigned n = osection[0].rawdataptr - fo->getBytesWritten() - identsize;
|
||||||
|
assert(n <= oh.filealign);
|
||||||
|
fo->write(ibuf, n);
|
||||||
|
}
|
||||||
fo->write(loader + codesize,identsize);
|
fo->write(loader + codesize,identsize);
|
||||||
infoWriting("loader", fo->getBytesWritten());
|
infoWriting("loader", fo->getBytesWritten());
|
||||||
fo->write(obuf,clen);
|
fo->write(obuf,clen);
|
||||||
@@ -1896,6 +1978,9 @@ void PackW32Pe::pack(OutputFile *fo)
|
|||||||
printf("%-13s: relocs : %8ld bytes\n", getName(), (long) soxrelocs);
|
printf("%-13s: relocs : %8ld bytes\n", getName(), (long) soxrelocs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// verify
|
||||||
|
verifyOverlappingDecompression();
|
||||||
|
|
||||||
// copy the overlay
|
// copy the overlay
|
||||||
copyOverlay(fo, overlay, &obuf);
|
copyOverlay(fo, overlay, &obuf);
|
||||||
|
|
||||||
@@ -2119,8 +2204,8 @@ void PackW32Pe::rebuildRelocs(upx_byte *& extrainfo)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
memcpy (obuf + ODADDR(PEDIR_RELOC) - rvamin,oxrelocs,soxrelocs);
|
memcpy (obuf + ODADDR(PEDIR_RELOC) - rvamin,oxrelocs,soxrelocs);
|
||||||
delete [] oxrelocs; oxrelocs = 0;
|
delete [] oxrelocs; oxrelocs = NULL;
|
||||||
wrkmem.free();
|
wrkmem.dealloc();
|
||||||
|
|
||||||
ODSIZE(PEDIR_RELOC) = soxrelocs;
|
ODSIZE(PEDIR_RELOC) = soxrelocs;
|
||||||
}
|
}
|
||||||
@@ -2159,7 +2244,7 @@ void PackW32Pe::rebuildResources(upx_byte *& extrainfo)
|
|||||||
unsigned origoffs = get_le32(r + res.offs() - 4);
|
unsigned origoffs = get_le32(r + res.offs() - 4);
|
||||||
res.newoffs() = origoffs;
|
res.newoffs() = origoffs;
|
||||||
memcpy(obuf + origoffs - rvamin,r + res.offs(),res.size());
|
memcpy(obuf + origoffs - rvamin,r + res.offs(),res.size());
|
||||||
if (icondir_count && res.itype() == 14)
|
if (icondir_count && res.itype() == RT_GROUP_ICON)
|
||||||
{
|
{
|
||||||
set_le16(obuf + origoffs - rvamin + 4,icondir_count);
|
set_le16(obuf + origoffs - rvamin + 4,icondir_count);
|
||||||
icondir_count = 0;
|
icondir_count = 0;
|
||||||
@@ -2195,13 +2280,13 @@ void PackW32Pe::unpack(OutputFile *fo)
|
|||||||
extrainfo += sizeof (oh);
|
extrainfo += sizeof (oh);
|
||||||
unsigned objs = oh.objects;
|
unsigned objs = oh.objects;
|
||||||
|
|
||||||
autoheap_array(pe_section_t, osection, objs);
|
Array(pe_section_t, osection, objs);
|
||||||
memcpy(osection,extrainfo,sizeof(pe_section_t) * objs);
|
memcpy(osection,extrainfo,sizeof(pe_section_t) * objs);
|
||||||
rvamin = osection[0].vaddr;
|
rvamin = osection[0].vaddr;
|
||||||
extrainfo += sizeof(pe_section_t) * objs;
|
extrainfo += sizeof(pe_section_t) * objs;
|
||||||
|
|
||||||
// read the noncompressed section
|
// read the noncompressed section
|
||||||
ibuf.free();
|
ibuf.dealloc();
|
||||||
ibuf.alloc(isection[2].size);
|
ibuf.alloc(isection[2].size);
|
||||||
fi->seek(isection[2].rawdataptr,SEEK_SET);
|
fi->seek(isection[2].rawdataptr,SEEK_SET);
|
||||||
fi->readx(ibuf,isection[2].size);
|
fi->readx(ibuf,isection[2].size);
|
||||||
@@ -2232,8 +2317,10 @@ void PackW32Pe::unpack(OutputFile *fo)
|
|||||||
ODSIZE(PEDIR_IAT) = 0;
|
ODSIZE(PEDIR_IAT) = 0;
|
||||||
ODADDR(PEDIR_BOUNDIM) = 0;
|
ODADDR(PEDIR_BOUNDIM) = 0;
|
||||||
ODSIZE(PEDIR_BOUNDIM) = 0;
|
ODSIZE(PEDIR_BOUNDIM) = 0;
|
||||||
|
|
||||||
// oh.headersize = osection[0].rawdataptr;
|
// oh.headersize = osection[0].rawdataptr;
|
||||||
oh.headersize = ALIGN_UP(pe_offset + sizeof(oh) + sizeof(pe_section_t) * objs, oh.filealign);
|
// oh.headersize = ALIGN_UP(pe_offset + sizeof(oh) + sizeof(pe_section_t) * objs, oh.filealign);
|
||||||
|
oh.headersize = rvamin;
|
||||||
oh.chksum = 0;
|
oh.chksum = 0;
|
||||||
|
|
||||||
// FIXME: ih.flags is checked here because of a bug in UPX 0.92
|
// FIXME: ih.flags is checked here because of a bug in UPX 0.92
|
||||||
@@ -2247,7 +2334,7 @@ void PackW32Pe::unpack(OutputFile *fo)
|
|||||||
// write decompressed file
|
// write decompressed file
|
||||||
if (fo)
|
if (fo)
|
||||||
{
|
{
|
||||||
ibuf.free();
|
ibuf.dealloc();
|
||||||
ibuf.alloc(osection[0].rawdataptr);
|
ibuf.alloc(osection[0].rawdataptr);
|
||||||
memset(ibuf,0,osection[0].rawdataptr);
|
memset(ibuf,0,osection[0].rawdataptr);
|
||||||
infoHeader("[Writing uncompressed file]");
|
infoHeader("[Writing uncompressed file]");
|
||||||
@@ -2261,7 +2348,7 @@ void PackW32Pe::unpack(OutputFile *fo)
|
|||||||
fo->write(obuf + osection[ic].vaddr - rvamin,ALIGN_UP(osection[ic].size,oh.filealign));
|
fo->write(obuf + osection[ic].vaddr - rvamin,ALIGN_UP(osection[ic].size,oh.filealign));
|
||||||
copyOverlay(fo, overlay, &obuf);
|
copyOverlay(fo, overlay, &obuf);
|
||||||
}
|
}
|
||||||
ibuf.free();
|
ibuf.dealloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2277,6 +2364,7 @@ void PackW32Pe::unpack(OutputFile *fo)
|
|||||||
<offset of extra info 4>
|
<offset of extra info 4>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
vi:ts=4:et
|
vi:ts=4:et
|
||||||
*/
|
*/
|
||||||
|
|||||||
+29
-11
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -47,10 +47,10 @@ class PackW32Pe : public Packer
|
|||||||
public:
|
public:
|
||||||
PackW32Pe(InputFile *f);
|
PackW32Pe(InputFile *f);
|
||||||
~PackW32Pe();
|
~PackW32Pe();
|
||||||
virtual int getVersion() const { return 12; }
|
virtual int getVersion() const { return 13; }
|
||||||
virtual int getFormat() const { return UPX_F_W32_PE; }
|
virtual int getFormat() const { return UPX_F_WIN32_PE; }
|
||||||
virtual const char *getName() const { return isrtm ? "rtm32/pe" : "win32/pe"; }
|
virtual const char *getName() const { return isrtm ? "rtm32/pe" : "win32/pe"; }
|
||||||
virtual int getCompressionMethod() const;
|
virtual const int *getCompressionMethods(int method, int level) const;
|
||||||
virtual const int *getFilters() const;
|
virtual const int *getFilters() const;
|
||||||
|
|
||||||
virtual void pack(OutputFile *fo);
|
virtual void pack(OutputFile *fo);
|
||||||
@@ -61,15 +61,16 @@ public:
|
|||||||
|
|
||||||
// unpacker capabilities
|
// unpacker capabilities
|
||||||
virtual bool canUnpackVersion(int version) const
|
virtual bool canUnpackVersion(int version) const
|
||||||
{ return (version == 12); }
|
{ return (version >= 12 && version <= 13); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
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;
|
||||||
bool isrtm;
|
bool isrtm;
|
||||||
bool readFileHeader();
|
|
||||||
|
|
||||||
unsigned processImports();
|
unsigned processImports();
|
||||||
void processImports(unsigned);
|
void processImports(unsigned);
|
||||||
@@ -158,8 +159,12 @@ protected:
|
|||||||
{
|
{
|
||||||
LE32 vaddr;
|
LE32 vaddr;
|
||||||
LE32 size;
|
LE32 size;
|
||||||
} ddirs[16];
|
}
|
||||||
} ih, oh;
|
__attribute_packed;
|
||||||
|
|
||||||
|
struct ddirs_t ddirs[16];
|
||||||
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
struct pe_section_t
|
struct pe_section_t
|
||||||
{
|
{
|
||||||
@@ -170,7 +175,11 @@ protected:
|
|||||||
LE32 rawdataptr;
|
LE32 rawdataptr;
|
||||||
char _[12];
|
char _[12];
|
||||||
LE32 flags;
|
LE32 flags;
|
||||||
} *isection;
|
}
|
||||||
|
__attribute_packed;
|
||||||
|
|
||||||
|
pe_header_t ih, oh;
|
||||||
|
pe_section_t *isection;
|
||||||
|
|
||||||
static unsigned virta2objnum (unsigned, pe_section_t *, unsigned);
|
static unsigned virta2objnum (unsigned, pe_section_t *, unsigned);
|
||||||
unsigned tryremove (unsigned, unsigned);
|
unsigned tryremove (unsigned, unsigned);
|
||||||
@@ -223,6 +232,15 @@ protected:
|
|||||||
DLL_FLAG = 0x2000,
|
DLL_FLAG = 0x2000,
|
||||||
FBIG_ENDIAN = 0x8000
|
FBIG_ENDIAN = 0x8000
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// predefined resource types
|
||||||
|
enum {
|
||||||
|
RT_CURSOR = 1, RT_BITMAP, RT_ICON, RT_MENU, RT_DIALOG, RT_STRING,
|
||||||
|
RT_FONTDIR, RT_FONT, RT_ACCELERATOR, RT_RCDATA, RT_MESSAGETABLE,
|
||||||
|
RT_GROUP_CURSOR, RT_GROUP_ICON = 14, RT_VERSION = 16, RT_DLGINCLUDE,
|
||||||
|
RT_PLUGPLAY = 19, RT_VXD, RT_ANICURSOR, RT_ANIICON, RT_HTML,
|
||||||
|
RT_MANIFEST, RT_LAST
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+79
-70
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -66,24 +66,54 @@ static const
|
|||||||
//
|
//
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
int PackWcle::getCompressionMethod() const
|
const int *PackWcle::getCompressionMethods(int method, int level) const
|
||||||
{
|
{
|
||||||
if (M_IS_NRV2B(opt->method))
|
return Packer::getDefaultCompressionMethods_le32(method, level);
|
||||||
return M_NRV2B_LE32;
|
|
||||||
if (M_IS_NRV2D(opt->method))
|
|
||||||
return M_NRV2D_LE32;
|
|
||||||
return opt->level > 1 && file_size >= 512*1024 ? M_NRV2D_LE32 : M_NRV2B_LE32;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const int *PackWcle::getFilters() const
|
const int *PackWcle::getFilters() const
|
||||||
{
|
{
|
||||||
static const int filters[] = { 0x26, 0x24, 0x14, 0x11, 0x16, 0x13,
|
static const int filters[] = {
|
||||||
0x25, 0x12, 0x15, -1 };
|
0x26, 0x24, 0x14, 0x11, 0x16, 0x13, 0x25, 0x12, 0x15,
|
||||||
|
-1 };
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int PackWcle::buildLoader(const Filter *ft)
|
||||||
|
{
|
||||||
|
// prepare loader
|
||||||
|
initLoader(nrv_loader,sizeof(nrv_loader));
|
||||||
|
addLoader("IDENTSTR""WCLEMAIN""UPX1HEAD""WCLECUTP""+0000000",
|
||||||
|
getDecompressor(),
|
||||||
|
"WCLEMAI2",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
if (ft->id)
|
||||||
|
{
|
||||||
|
assert(ft->calls > 0);
|
||||||
|
addLoader(ft->addvalue ? "WCCTTPOS" : "WCCTTNUL", NULL);
|
||||||
|
addFilter32(ft->id);
|
||||||
|
}
|
||||||
|
#if 1
|
||||||
|
// FIXME: if (has_relocation)
|
||||||
|
{
|
||||||
|
addLoader("WCRELOC1""RELOC320",
|
||||||
|
big_relocs ? "REL32BIG" : "",
|
||||||
|
"RELOC32J",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
addLoader(has_extra_code ? "WCRELSEL" : "",
|
||||||
|
"WCLEMAI4",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
return getLoaderSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// util
|
// util
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
@@ -97,7 +127,9 @@ void PackWcle::handleStub(OutputFile *fo)
|
|||||||
|
|
||||||
bool PackWcle::canPack()
|
bool PackWcle::canPack()
|
||||||
{
|
{
|
||||||
return LeFile::readFileHeader();
|
if (!LeFile::readFileHeader())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -132,6 +164,7 @@ void PackWcle::encodeEntryTable()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//if (Opt_debug) printf("%d entries encoded.\n",n);
|
//if (Opt_debug) printf("%d entries encoded.\n",n);
|
||||||
|
UNUSED(n);
|
||||||
|
|
||||||
soentries = p - ientries + 1;
|
soentries = p - ientries + 1;
|
||||||
oentries = ientries;
|
oentries = ientries;
|
||||||
@@ -175,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;
|
||||||
@@ -229,25 +262,24 @@ void PackWcle::encodeFixups()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int PackWcle::preprocessFixups()
|
void PackWcle::preprocessFixups()
|
||||||
{
|
{
|
||||||
unsigned ic,jc;
|
big_relocs = 0;
|
||||||
int big;
|
|
||||||
|
|
||||||
MemBuffer counts_buf((objects+2)*sizeof(unsigned));
|
unsigned ic,jc;
|
||||||
unsigned *counts = (unsigned *) (unsigned char *) counts_buf;
|
|
||||||
|
Array(unsigned, counts, objects+2);
|
||||||
countFixups(counts);
|
countFixups(counts);
|
||||||
|
|
||||||
for (ic = jc = 0; ic < objects; ic++)
|
for (ic = jc = 0; ic < objects; ic++)
|
||||||
jc += counts[ic];
|
jc += counts[ic];
|
||||||
|
|
||||||
MemBuffer rl(jc);
|
ByteArray(rl, jc);
|
||||||
MemBuffer srf(counts[objects+0]+1);
|
ByteArray(srf, counts[objects+0]+1);
|
||||||
MemBuffer slf(counts[objects+1]+1);
|
ByteArray(slf, counts[objects+1]+1);
|
||||||
|
|
||||||
upx_byte *selector_fixups = srf;
|
upx_byte *selector_fixups = srf;
|
||||||
upx_byte *selfrel_fixups = slf;
|
upx_byte *selfrel_fixups = slf;
|
||||||
|
|
||||||
unsigned rc = 0;
|
unsigned rc = 0;
|
||||||
|
|
||||||
upx_byte *fix = ifixups;
|
upx_byte *fix = ifixups;
|
||||||
@@ -255,7 +287,7 @@ int PackWcle::preprocessFixups()
|
|||||||
{
|
{
|
||||||
while ((unsigned)(fix - ifixups) < get_le32(ifpage_table+ic+1))
|
while ((unsigned)(fix - ifixups) < get_le32(ifpage_table+ic+1))
|
||||||
{
|
{
|
||||||
const short fixp2 = get_le16(fix+2);
|
const int fixp2 = get_le16_signed(fix+2);
|
||||||
unsigned value;
|
unsigned value;
|
||||||
|
|
||||||
switch (*fix)
|
switch (*fix)
|
||||||
@@ -351,7 +383,7 @@ int PackWcle::preprocessFixups()
|
|||||||
delete[] ifixups;
|
delete[] ifixups;
|
||||||
ifixups = new upx_byte[1000];
|
ifixups = new upx_byte[1000];
|
||||||
}
|
}
|
||||||
fix = optimizeReloc32 (rl,rc,ifixups,iimage,1,&big);
|
fix = optimizeReloc32 (rl,rc,ifixups,iimage,1,&big_relocs);
|
||||||
has_extra_code = srf != selector_fixups;
|
has_extra_code = srf != selector_fixups;
|
||||||
// FIXME: this could be removed if has_extra_code = false
|
// FIXME: this could be removed if has_extra_code = false
|
||||||
// but then we'll need a flag
|
// but then we'll need a flag
|
||||||
@@ -365,9 +397,9 @@ int PackWcle::preprocessFixups()
|
|||||||
fix += 4;
|
fix += 4;
|
||||||
|
|
||||||
sofixups = fix - ifixups;
|
sofixups = fix - ifixups;
|
||||||
return big;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define RESERVED 0x1000
|
#define RESERVED 0x1000
|
||||||
void PackWcle::encodeImage(const Filter *ft)
|
void PackWcle::encodeImage(const Filter *ft)
|
||||||
{
|
{
|
||||||
@@ -387,8 +419,10 @@ 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();
|
||||||
overlapoh = findOverlapOverhead(oimage+RESERVED, 512);
|
ph.overlap_overhead = findOverlapOverhead(oimage+RESERVED, 512);
|
||||||
ibuf.free();
|
buildLoader(ft);
|
||||||
|
|
||||||
|
ibuf.dealloc();
|
||||||
soimage = (ph.c_len + 3) &~ 3;
|
soimage = (ph.c_len + 3) &~ 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -418,67 +452,40 @@ void PackWcle::pack(OutputFile *fo)
|
|||||||
readImage();
|
readImage();
|
||||||
readNonResidentNames();
|
readNonResidentNames();
|
||||||
|
|
||||||
if (find_le32(iimage,20,get_le32("UPX ")) >= 0)
|
// if (find_le32(iimage,20,get_le32("UPX ")) >= 0)
|
||||||
|
if (find_le32(iimage,UPX_MIN(soimage,256u),UPX_MAGIC_LE32) >= 0)
|
||||||
throwAlreadyPacked();
|
throwAlreadyPacked();
|
||||||
|
|
||||||
if (ih.init_ss_object != objects)
|
if (ih.init_ss_object != objects)
|
||||||
throwCantPack("the stack is not in the last object");
|
throwCantPack("the stack is not in the last object");
|
||||||
|
|
||||||
int big = preprocessFixups();
|
preprocessFixups();
|
||||||
|
|
||||||
const unsigned text_size = IOT(ih.init_cs_object-1,npages) * mps;
|
const unsigned text_size = IOT(ih.init_cs_object-1,npages) * mps;
|
||||||
const unsigned text_vaddr = IOT(ih.init_cs_object-1,my_base_address);
|
const unsigned text_vaddr = IOT(ih.init_cs_object-1,my_base_address);
|
||||||
|
|
||||||
// filter
|
|
||||||
Filter ft(opt->level);
|
|
||||||
tryFilters(&ft, iimage+text_vaddr, text_size, text_vaddr);
|
|
||||||
|
|
||||||
// attach some useful data at the end of preprocessed fixups
|
// attach some useful data at the end of preprocessed fixups
|
||||||
ifixups[sofixups++] = (unsigned char) ih.automatic_data_object;
|
ifixups[sofixups++] = (unsigned char) ih.automatic_data_object;
|
||||||
unsigned ic = objects*sizeof(*iobject_table);
|
unsigned ic = objects*sizeof(*iobject_table);
|
||||||
memcpy(ifixups+sofixups,iobject_desc,ic);
|
memcpy(ifixups+sofixups,iobject_desc,ic);
|
||||||
iobject_desc.free();
|
iobject_desc.dealloc();
|
||||||
|
|
||||||
sofixups += ic;
|
sofixups += ic;
|
||||||
set_le32(ifixups+sofixups,ih.init_esp_offset+IOT(ih.init_ss_object-1,my_base_address)); // old stack pointer
|
set_le32(ifixups+sofixups,ih.init_esp_offset+IOT(ih.init_ss_object-1,my_base_address)); // old stack pointer
|
||||||
set_le32(ifixups+sofixups+4,ih.init_eip_offset+text_vaddr); // real entry point
|
set_le32(ifixups+sofixups+4,ih.init_eip_offset+text_vaddr); // real entry point
|
||||||
set_le32(ifixups+sofixups+8,mps*pages); // virtual address of unpacked relocations
|
set_le32(ifixups+sofixups+8,mps*pages); // virtual address of unpacked relocations
|
||||||
ifixups[sofixups+12] = (unsigned char) objects;
|
ifixups[sofixups+12] = (unsigned char) (unsigned) objects;
|
||||||
sofixups += 13;
|
sofixups += 13;
|
||||||
|
|
||||||
|
// filter
|
||||||
|
Filter ft(ph.level);
|
||||||
|
tryFilters(&ft, iimage+text_vaddr, text_size, text_vaddr);
|
||||||
|
|
||||||
encodeImage(&ft);
|
encodeImage(&ft);
|
||||||
|
|
||||||
// verify filter
|
// verify filter
|
||||||
ft.verifyUnfilter();
|
ft.verifyUnfilter();
|
||||||
|
|
||||||
// prepare loader
|
|
||||||
initLoader(nrv_loader,sizeof(nrv_loader));
|
|
||||||
addLoader("IDENTSTR""WCLEMAIN""UPX1HEAD""WCLECUTP""+0000000",
|
|
||||||
getDecompressor(),
|
|
||||||
"WCLEMAI2",
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
if (ft.id)
|
|
||||||
{
|
|
||||||
assert(ft.calls > 0);
|
|
||||||
addLoader(text_vaddr ? "WCCTTPOS" : "WCCTTNUL",NULL);
|
|
||||||
addFilter32(ft.id);
|
|
||||||
}
|
|
||||||
#if 1
|
|
||||||
// FIXME: if (has_relocation)
|
|
||||||
{
|
|
||||||
addLoader("WCRELOC1""RELOC320",
|
|
||||||
big ? "REL32BIG" : "",
|
|
||||||
"RELOC32J",
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
addLoader(has_extra_code ? "WCRELSEL" : "",
|
|
||||||
"WCLEMAI4",
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
const unsigned lsize = getLoaderSize();
|
const unsigned lsize = getLoaderSize();
|
||||||
neweip = getLoaderSection("WCLEMAIN");
|
neweip = getLoaderSection("WCLEMAIN");
|
||||||
int e_len = getLoaderSectionStart("WCLECUTP");
|
int e_len = getLoaderSectionStart("WCLECUTP");
|
||||||
@@ -508,7 +515,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));
|
||||||
@@ -531,7 +538,7 @@ void PackWcle::pack(OutputFile *fo)
|
|||||||
|
|
||||||
// copy the overlay
|
// copy the overlay
|
||||||
const unsigned overlaystart = ih.data_pages_offset + exe_offset
|
const unsigned overlaystart = ih.data_pages_offset + exe_offset
|
||||||
+ mps * (pages - 1) + ih.bytes_on_last_page;
|
+ getImageSize();
|
||||||
const unsigned overlay = file_size - overlaystart - ih.non_resident_name_table_length;
|
const unsigned overlay = file_size - overlaystart - ih.non_resident_name_table_length;
|
||||||
checkOverlay(overlay);
|
checkOverlay(overlay);
|
||||||
copyOverlay(fo, overlay, &oimage);
|
copyOverlay(fo, overlay, &oimage);
|
||||||
@@ -550,7 +557,7 @@ void PackWcle::decodeFixups()
|
|||||||
{
|
{
|
||||||
upx_byte *p = oimage + soimage;
|
upx_byte *p = oimage + soimage;
|
||||||
|
|
||||||
iimage.free();
|
iimage.dealloc();
|
||||||
|
|
||||||
MemBuffer tmpbuf;
|
MemBuffer tmpbuf;
|
||||||
unsigned fixupn = unoptimizeReloc32(&p,oimage,&tmpbuf,1);
|
unsigned fixupn = unoptimizeReloc32(&p,oimage,&tmpbuf,1);
|
||||||
@@ -568,7 +575,7 @@ void PackWcle::decodeFixups()
|
|||||||
set_le32(oimage+jc,r);
|
set_le32(oimage+jc,r);
|
||||||
}
|
}
|
||||||
set_le32(wrkmem+ic*8,0xFFFFFFFF); // end of 32-bit offset fixups
|
set_le32(wrkmem+ic*8,0xFFFFFFFF); // end of 32-bit offset fixups
|
||||||
tmpbuf.free();
|
tmpbuf.dealloc();
|
||||||
|
|
||||||
// selector fixups and self-relative fixups
|
// selector fixups and self-relative fixups
|
||||||
const upx_byte *selector_fixups = p;
|
const upx_byte *selector_fixups = p;
|
||||||
@@ -747,7 +754,9 @@ int PackWcle::canUnpack()
|
|||||||
return false;
|
return false;
|
||||||
fi->seek(exe_offset + ih.data_pages_offset, SEEK_SET);
|
fi->seek(exe_offset + ih.data_pages_offset, SEEK_SET);
|
||||||
// FIXME: 1024 could be too large for some files
|
// FIXME: 1024 could be too large for some files
|
||||||
return readPackHeader(1024) ? 1 : -1;
|
//int len = 1024;
|
||||||
|
int len = UPX_MIN(getImageSize(), 256u);
|
||||||
|
return readPackHeader(len) ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -772,7 +781,7 @@ void PackWcle::unpack(OutputFile *fo)
|
|||||||
handleStub(fo);
|
handleStub(fo);
|
||||||
|
|
||||||
readObjectTable();
|
readObjectTable();
|
||||||
iobject_desc.free();
|
iobject_desc.dealloc();
|
||||||
readPageMap();
|
readPageMap();
|
||||||
readResidentNames();
|
readResidentNames();
|
||||||
readEntryTable();
|
readEntryTable();
|
||||||
@@ -816,7 +825,7 @@ void PackWcle::unpack(OutputFile *fo)
|
|||||||
|
|
||||||
// copy the overlay
|
// copy the overlay
|
||||||
const unsigned overlaystart = ih.data_pages_offset + exe_offset
|
const unsigned overlaystart = ih.data_pages_offset + exe_offset
|
||||||
+ mps * (pages - 1) + ih.bytes_on_last_page;
|
+ getImageSize();
|
||||||
const unsigned overlay = file_size - overlaystart - ih.non_resident_name_table_length;
|
const unsigned overlay = file_size - overlaystart - ih.non_resident_name_table_length;
|
||||||
checkOverlay(overlay);
|
checkOverlay(overlay);
|
||||||
copyOverlay(fo, overlay, &oimage);
|
copyOverlay(fo, overlay, &oimage);
|
||||||
|
|||||||
+9
-7
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -39,10 +39,10 @@ class PackWcle : public Packer, public LeFile
|
|||||||
typedef Packer super;
|
typedef Packer super;
|
||||||
public:
|
public:
|
||||||
PackWcle(InputFile *f) : super(f), LeFile(f){};
|
PackWcle(InputFile *f) : super(f), LeFile(f){};
|
||||||
virtual int getVersion() const { return 12; }
|
virtual int getVersion() const { return 13; }
|
||||||
virtual int getFormat() const { return UPX_F_WC_LE; }
|
virtual int getFormat() const { return UPX_F_WC_LE; }
|
||||||
virtual const char *getName() const { return "watcom/le"; }
|
virtual const char *getName() const { return "watcom/le"; }
|
||||||
virtual int getCompressionMethod() const;
|
virtual const int *getCompressionMethods(int method, int level) const;
|
||||||
virtual const int *getFilters() const;
|
virtual const int *getFilters() const;
|
||||||
|
|
||||||
virtual void pack(OutputFile *fo);
|
virtual void pack(OutputFile *fo);
|
||||||
@@ -54,6 +54,8 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
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();
|
||||||
@@ -66,7 +68,7 @@ protected:
|
|||||||
virtual void encodeEntryTable();
|
virtual void encodeEntryTable();
|
||||||
virtual void decodeEntryTable();
|
virtual void decodeEntryTable();
|
||||||
|
|
||||||
virtual int preprocessFixups();
|
virtual void preprocessFixups();
|
||||||
virtual void encodeFixups();
|
virtual void encodeFixups();
|
||||||
virtual void decodeFixups();
|
virtual void decodeFixups();
|
||||||
|
|
||||||
@@ -78,8 +80,8 @@ protected:
|
|||||||
// temporary copy of the object descriptors
|
// temporary copy of the object descriptors
|
||||||
MemBuffer iobject_desc;
|
MemBuffer iobject_desc;
|
||||||
|
|
||||||
|
int big_relocs;
|
||||||
bool has_extra_code;
|
bool has_extra_code;
|
||||||
unsigned overlapoh;
|
|
||||||
unsigned neweip;
|
unsigned neweip;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+298
-231
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -150,13 +150,13 @@ bool Packer::compress(upx_bytep in, upx_bytep out,
|
|||||||
return false;
|
return false;
|
||||||
#else
|
#else
|
||||||
ph.c_len = 0;
|
ph.c_len = 0;
|
||||||
|
assert(ph.level >= 1); assert(ph.level <= 10);
|
||||||
|
|
||||||
const int level = ph.level;
|
// save current checksums
|
||||||
assert(level >= 1); assert(level <= 10);
|
ph.saved_u_adler = ph.u_adler;
|
||||||
|
ph.saved_c_adler = ph.c_adler;
|
||||||
// update checksum of uncompressed data
|
// update checksum of uncompressed data
|
||||||
const unsigned saved_u_adler = ph.u_adler;
|
ph.u_adler = upx_adler32(in, ph.u_len, ph.u_adler);
|
||||||
ph.u_adler = upx_adler32(ph.u_adler,in,ph.u_len);
|
|
||||||
|
|
||||||
// set compression paramters
|
// set compression paramters
|
||||||
upx_compress_config_t conf;
|
upx_compress_config_t conf;
|
||||||
@@ -172,7 +172,7 @@ bool Packer::compress(upx_bytep in, upx_bytep out,
|
|||||||
#if 0
|
#if 0
|
||||||
else
|
else
|
||||||
// this is based on experimentation
|
// this is based on experimentation
|
||||||
conf.c_flags = (level >= 7) ? 0 : 1 | 2;
|
conf.c_flags = (ph.level >= 7) ? 0 : 1 | 2;
|
||||||
#endif
|
#endif
|
||||||
if (opt->crp.p_level != -1)
|
if (opt->crp.p_level != -1)
|
||||||
conf.p_level = opt->crp.p_level;
|
conf.p_level = opt->crp.p_level;
|
||||||
@@ -186,7 +186,7 @@ bool Packer::compress(upx_bytep in, upx_bytep out,
|
|||||||
// Avoid too many progress bar updates. 64 is s->bar_len in ui.cpp.
|
// Avoid too many progress bar updates. 64 is s->bar_len in ui.cpp.
|
||||||
unsigned step = (ph.u_len < 64*1024) ? 0 : ph.u_len / 64;
|
unsigned step = (ph.u_len < 64*1024) ? 0 : ph.u_len / 64;
|
||||||
#if defined(WITH_NRV)
|
#if defined(WITH_NRV)
|
||||||
if ((level >= 7) || (level >= 4 && ph.u_len >= 512*1024))
|
if (ph.level >= 7 || (ph.level >= 4 && ph.u_len >= 512*1024))
|
||||||
step = 0;
|
step = 0;
|
||||||
#endif
|
#endif
|
||||||
if (ui_pass >= 0)
|
if (ui_pass >= 0)
|
||||||
@@ -201,12 +201,15 @@ bool Packer::compress(upx_bytep in, upx_bytep out,
|
|||||||
memset(result, 0, sizeof(result));
|
memset(result, 0, sizeof(result));
|
||||||
int r = upx_compress(in, ph.u_len, out, &ph.c_len,
|
int r = upx_compress(in, ph.u_len, out, &ph.c_len,
|
||||||
uip->getCallback(),
|
uip->getCallback(),
|
||||||
ph.method, level, &conf, result);
|
ph.method, ph.level, &conf, result);
|
||||||
|
|
||||||
|
//uip->finalCallback(ph.u_len, ph.c_len);
|
||||||
|
uip->endCallback();
|
||||||
|
|
||||||
if (r == UPX_E_OUT_OF_MEMORY)
|
if (r == UPX_E_OUT_OF_MEMORY)
|
||||||
throwCantPack("out of memory");
|
throwCantPack("out of memory");
|
||||||
if (r != UPX_E_OK)
|
if (r != UPX_E_OK)
|
||||||
throwInternalError("compression failed");
|
throwInternalError("compression failed");
|
||||||
//uip->finalCallback(ph.u_len, ph.c_len);
|
|
||||||
|
|
||||||
//ph.min_offset_found = result[0];
|
//ph.min_offset_found = result[0];
|
||||||
ph.max_offset_found = result[1];
|
ph.max_offset_found = result[1];
|
||||||
@@ -219,8 +222,6 @@ bool Packer::compress(upx_bytep in, upx_bytep out,
|
|||||||
assert(max_offset == 0 || max_offset >= ph.max_offset_found);
|
assert(max_offset == 0 || max_offset >= ph.max_offset_found);
|
||||||
assert(max_match == 0 || max_match >= ph.max_match_found);
|
assert(max_match == 0 || max_match >= ph.max_match_found);
|
||||||
|
|
||||||
uip->endCallback();
|
|
||||||
|
|
||||||
//printf("\nPacker::compress: %d/%d: %7d -> %7d\n", ph.method, ph.level, ph.u_len, ph.c_len);
|
//printf("\nPacker::compress: %d/%d: %7d -> %7d\n", ph.method, ph.level, ph.u_len, ph.c_len);
|
||||||
if (!checkCompressionRatio(ph.u_len, ph.c_len))
|
if (!checkCompressionRatio(ph.u_len, ph.c_len))
|
||||||
return false;
|
return false;
|
||||||
@@ -229,9 +230,9 @@ bool Packer::compress(upx_bytep in, upx_bytep out,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// update checksum of compressed data
|
// update checksum of compressed data
|
||||||
ph.c_adler = upx_adler32(ph.c_adler,out,ph.c_len);
|
ph.c_adler = upx_adler32(out, ph.c_len, ph.c_adler);
|
||||||
// Decompress and verify. Skip this when using the fastest level.
|
// Decompress and verify. Skip this when using the fastest level.
|
||||||
if (level > 1)
|
if (ph.level > 1)
|
||||||
{
|
{
|
||||||
// decompress
|
// decompress
|
||||||
unsigned new_len = ph.u_len;
|
unsigned new_len = ph.u_len;
|
||||||
@@ -243,7 +244,7 @@ bool Packer::compress(upx_bytep in, upx_bytep out,
|
|||||||
throwInternalError("decompression failed (size error)");
|
throwInternalError("decompression failed (size error)");
|
||||||
|
|
||||||
// verify decompression
|
// verify decompression
|
||||||
if (ph.u_adler != upx_adler32(saved_u_adler,in,ph.u_len))
|
if (ph.u_adler != upx_adler32(in, ph.u_len, ph.saved_u_adler))
|
||||||
throwInternalError("decompression failed (checksum error)");
|
throwInternalError("decompression failed (checksum error)");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -256,9 +257,6 @@ bool Packer::checkCompressionRatio(unsigned u_len, unsigned c_len) const
|
|||||||
assert((int)u_len > 0);
|
assert((int)u_len > 0);
|
||||||
assert((int)c_len > 0);
|
assert((int)c_len > 0);
|
||||||
|
|
||||||
// this assertion may fail if we compress the BSS segment -- disabled
|
|
||||||
//assert((off_t)u_len < file_size);
|
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
if (c_len + 512 >= u_len) // min. 512 bytes gain
|
if (c_len + 512 >= u_len) // min. 512 bytes gain
|
||||||
return false;
|
return false;
|
||||||
@@ -274,8 +272,8 @@ bool Packer::checkCompressionRatio(unsigned u_len, unsigned c_len) const
|
|||||||
|
|
||||||
bool Packer::checkFinalCompressionRatio(const OutputFile *fo) const
|
bool Packer::checkFinalCompressionRatio(const OutputFile *fo) const
|
||||||
{
|
{
|
||||||
unsigned u_len = file_size;
|
const unsigned u_len = file_size;
|
||||||
unsigned c_len = fo->getBytesWritten();
|
const unsigned c_len = fo->getBytesWritten();
|
||||||
|
|
||||||
assert((int)u_len > 0);
|
assert((int)u_len > 0);
|
||||||
assert((int)c_len > 0);
|
assert((int)c_len > 0);
|
||||||
@@ -283,12 +281,17 @@ bool Packer::checkFinalCompressionRatio(const OutputFile *fo) const
|
|||||||
if (c_len + 4096 <= u_len) // ok if we have 4096 bytes gain
|
if (c_len + 4096 <= u_len) // ok if we have 4096 bytes gain
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return checkCompressionRatio(u_len, c_len);
|
if (c_len + 512 >= u_len) // min. 512 bytes gain
|
||||||
|
return false;
|
||||||
|
if (c_len >= u_len - u_len / 8) // min. 12.5% gain
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
// decompress
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
void Packer::decompress(const upx_bytep in, upx_bytep out,
|
void Packer::decompress(const upx_bytep in, upx_bytep out,
|
||||||
@@ -299,8 +302,7 @@ void Packer::decompress(const upx_bytep in, upx_bytep out,
|
|||||||
// verify checksum of compressed data
|
// verify checksum of compressed data
|
||||||
if (verify_checksum)
|
if (verify_checksum)
|
||||||
{
|
{
|
||||||
adler = upx_adler32(0,NULL,0);
|
adler = upx_adler32(in, ph.c_len, ph.saved_c_adler);
|
||||||
adler = upx_adler32(adler,in,ph.c_len);
|
|
||||||
if (adler != ph.c_adler)
|
if (adler != ph.c_adler)
|
||||||
throwChecksumError();
|
throwChecksumError();
|
||||||
}
|
}
|
||||||
@@ -314,8 +316,7 @@ void Packer::decompress(const upx_bytep in, upx_bytep out,
|
|||||||
// verify checksum of decompressed data
|
// verify checksum of decompressed data
|
||||||
if (verify_checksum)
|
if (verify_checksum)
|
||||||
{
|
{
|
||||||
adler = upx_adler32(0,NULL,0);
|
adler = upx_adler32(out, ph.u_len, ph.saved_u_adler);
|
||||||
adler = upx_adler32(adler,out,ph.u_len);
|
|
||||||
if (adler != ph.u_adler)
|
if (adler != ph.u_adler)
|
||||||
throwChecksumError();
|
throwChecksumError();
|
||||||
}
|
}
|
||||||
@@ -323,7 +324,7 @@ void Packer::decompress(const upx_bytep in, upx_bytep out,
|
|||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
// overlapping decompression
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
bool Packer::testOverlappingDecompression(const upx_bytep buf,
|
bool Packer::testOverlappingDecompression(const upx_bytep buf,
|
||||||
@@ -354,18 +355,16 @@ bool Packer::testOverlappingDecompression(const upx_bytep buf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Packer::verifyOverlappingDecompression(MemBuffer *buf,
|
void Packer::verifyOverlappingDecompression()
|
||||||
unsigned overlap_overhead)
|
|
||||||
{
|
{
|
||||||
#if defined(UNUPX)
|
assert(ph.c_len < ph.u_len);
|
||||||
#else
|
assert((int)ph.overlap_overhead > 0);
|
||||||
// FIXME (well, this is complete paranoia anyway)
|
#if 1 && !defined(UNUPX)
|
||||||
//
|
|
||||||
// Idea:
|
// Idea:
|
||||||
// buf was allocated with MemBuffer.allocForCompression(), and
|
// obuf[] was allocated with MemBuffer::allocForCompression(), and
|
||||||
// its contents are no longer needed, i.e. the compressed data
|
// its contents are no longer needed, i.e. the compressed data
|
||||||
// must have been already written.
|
// must have been already written.
|
||||||
// We now could perform a real overlapping decompression and
|
// We now can perform a real overlapping decompression and
|
||||||
// verify the checksum.
|
// verify the checksum.
|
||||||
//
|
//
|
||||||
// Note:
|
// Note:
|
||||||
@@ -375,9 +374,15 @@ void Packer::verifyOverlappingDecompression(MemBuffer *buf,
|
|||||||
//
|
//
|
||||||
// See also:
|
// See also:
|
||||||
// Filter::verifyUnfilter()
|
// Filter::verifyUnfilter()
|
||||||
#endif
|
|
||||||
UNUSED(buf);
|
if (ph.level == 1)
|
||||||
UNUSED(overlap_overhead);
|
return;
|
||||||
|
unsigned offset = (ph.u_len + ph.overlap_overhead) - ph.c_len;
|
||||||
|
if (offset + ph.c_len > obuf.getSize())
|
||||||
|
return;
|
||||||
|
memmove(obuf + offset, obuf, ph.c_len);
|
||||||
|
decompress(obuf + offset, obuf, true);
|
||||||
|
#endif /* !UNUPX */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -452,7 +457,7 @@ void Packer::handleStub(InputFile *fif, OutputFile *fo, long size)
|
|||||||
{
|
{
|
||||||
// copy stub from exe
|
// copy stub from exe
|
||||||
info("Copying original stub: %ld bytes", size);
|
info("Copying original stub: %ld bytes", size);
|
||||||
autoheap_array(char, stub, size);
|
ByteArray(stub, size);
|
||||||
fif->seek(0,SEEK_SET);
|
fif->seek(0,SEEK_SET);
|
||||||
fif->readx(stub,size);
|
fif->readx(stub,size);
|
||||||
fo->write(stub,size);
|
fo->write(stub,size);
|
||||||
@@ -493,7 +498,7 @@ void Packer::copyOverlay(OutputFile *fo, unsigned overlay,
|
|||||||
}
|
}
|
||||||
info("Copying overlay: %d bytes", overlay);
|
info("Copying overlay: %d bytes", overlay);
|
||||||
if (do_seek)
|
if (do_seek)
|
||||||
fi->seek(-(long)overlay, SEEK_END);
|
fi->seek(-(off_t)overlay, SEEK_END);
|
||||||
|
|
||||||
// get buffer size, align to improve i/o speed
|
// get buffer size, align to improve i/o speed
|
||||||
unsigned buf_size = buf->getSize();
|
unsigned buf_size = buf->getSize();
|
||||||
@@ -556,26 +561,29 @@ unsigned Packer::getRandomId() const
|
|||||||
void Packer::initPackHeader()
|
void Packer::initPackHeader()
|
||||||
{
|
{
|
||||||
memset(&ph, 0, sizeof(ph));
|
memset(&ph, 0, sizeof(ph));
|
||||||
ph.magic = UPX_MAGIC_LE32; // "UPX!"
|
|
||||||
ph.version = getVersion();
|
ph.version = getVersion();
|
||||||
ph.format = getFormat();
|
ph.format = getFormat();
|
||||||
ph.method = -1;
|
ph.method = -1;
|
||||||
ph.level = -1;
|
ph.level = -1;
|
||||||
ph.c_adler = ph.u_adler = upx_adler32(0,NULL,0);
|
ph.u_adler = ph.c_adler = ph.saved_u_adler = ph.saved_c_adler = upx_adler32(NULL,0);
|
||||||
ph.buf_offset = -1;
|
ph.buf_offset = -1;
|
||||||
ph.u_file_size = file_size;
|
ph.u_file_size = file_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// this is called directly after canPack() from class PackMaster
|
// this is called directly after canPack() from class PackMaster
|
||||||
void Packer::updatePackHeader()
|
void Packer::updatePackHeader()
|
||||||
{
|
{
|
||||||
// update our local options
|
assert(opt->cmd == CMD_COMPRESS);
|
||||||
if (opt->level < 0)
|
//
|
||||||
opt->level = file_size < 512*1024 ? 8 : 7;
|
const int *m = getCompressionMethods(opt->method, opt->level);
|
||||||
opt->method = getCompressionMethod();
|
ph.method = m[0];
|
||||||
// set ph
|
|
||||||
ph.level = opt->level;
|
ph.level = opt->level;
|
||||||
ph.method = opt->method;
|
if (ph.level < 0)
|
||||||
|
ph.level = file_size < 512*1024 ? 8 : 7;
|
||||||
|
//
|
||||||
|
assert(isValidCompressionMethod(ph.method));
|
||||||
|
assert(1 <= ph.level && ph.level <= 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -584,7 +592,7 @@ int Packer::patchPackHeader(void *b, int blen)
|
|||||||
const int size = ph.getPackHeaderSize();
|
const int size = ph.getPackHeaderSize();
|
||||||
assert(isValidFilter(ph.filter));
|
assert(isValidFilter(ph.filter));
|
||||||
|
|
||||||
int boff = find_le32(b, blen, ph.magic);
|
int boff = find_le32(b, blen, UPX_MAGIC_LE32);
|
||||||
checkPatch(b, blen, boff, size);
|
checkPatch(b, blen, boff, size);
|
||||||
|
|
||||||
unsigned char *p = (unsigned char *)b + boff;
|
unsigned char *p = (unsigned char *)b + boff;
|
||||||
@@ -621,8 +629,8 @@ bool Packer::getPackHeader(void *b, int blen)
|
|||||||
throwCantUnpack("header size corrupted");
|
throwCantUnpack("header size corrupted");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (ph.method < M_NRV2B_LE32 || ph.method > M_NRV2D_LE16)
|
if (!isValidCompressionMethod(ph.method))
|
||||||
throwCantUnpack("unknown compression method");
|
throwCantUnpack("unknown compression method (try a newer version of UPX)");
|
||||||
|
|
||||||
// Some formats might be able to unpack "subformats". Ask them.
|
// Some formats might be able to unpack "subformats". Ask them.
|
||||||
if (!testUnpackFormat(ph.format))
|
if (!testUnpackFormat(ph.format))
|
||||||
@@ -643,6 +651,26 @@ bool Packer::readPackHeader(int len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Packer::checkAlreadyPacked(void *b, int blen)
|
||||||
|
{
|
||||||
|
int boff = find_le32(b, blen, UPX_MAGIC_LE32);
|
||||||
|
if (boff < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// FIXME: could add some more checks to verify that this
|
||||||
|
// is a real PackHeader, e.g.
|
||||||
|
//
|
||||||
|
//PackHeader tmp;
|
||||||
|
//if (!tmp.fillPackHeader((unsigned char *)b + boff, blen - boff))
|
||||||
|
// return;
|
||||||
|
//
|
||||||
|
// This also would require that the buffer in `b' holds
|
||||||
|
// the full PackHeader, and not only the 4 magic bytes.
|
||||||
|
|
||||||
|
throwAlreadyPacked();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// patch util for loader
|
// patch util for loader
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
@@ -781,8 +809,7 @@ int Packer::patchVersion(void *b, int blen)
|
|||||||
checkPatch(b, blen, boff, 14);
|
checkPatch(b, blen, boff, 14);
|
||||||
|
|
||||||
unsigned char *p = (unsigned char *)b + boff + 9;
|
unsigned char *p = (unsigned char *)b + boff + 9;
|
||||||
memset(p, ' ', 4);
|
memcpy(p, UPX_VERSION_STRING4, 4);
|
||||||
memcpy(p, UPX_VERSION_STRING, UPX_MIN(strlen(UPX_VERSION_STRING), 4));
|
|
||||||
|
|
||||||
return boff;
|
return boff;
|
||||||
}
|
}
|
||||||
@@ -884,33 +911,114 @@ unsigned Packer::unoptimizeReloc32(upx_byte **in, upx_byte *image,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// compression method util
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
bool Packer::isValidCompressionMethod(int method)
|
||||||
|
{
|
||||||
|
return (method >= M_NRV2B_LE32 && method <= M_NRV2E_LE16);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const int *Packer::getDefaultCompressionMethods_8(int method, int level, int small) const
|
||||||
|
{
|
||||||
|
static const int m_nrv2b[] = { M_NRV2B_8, M_NRV2D_8, M_NRV2E_8, -1 };
|
||||||
|
static const int m_nrv2d[] = { M_NRV2D_8, M_NRV2B_8, M_NRV2E_8, -1 };
|
||||||
|
static const int m_nrv2e[] = { M_NRV2E_8, M_NRV2B_8, M_NRV2D_8, -1 };
|
||||||
|
|
||||||
|
if (small < 0)
|
||||||
|
small = file_size <= 512*1024;
|
||||||
|
if (M_IS_NRV2B(method))
|
||||||
|
return m_nrv2b;
|
||||||
|
if (M_IS_NRV2D(method))
|
||||||
|
return m_nrv2d;
|
||||||
|
if (M_IS_NRV2E(method))
|
||||||
|
return m_nrv2e;
|
||||||
|
if (level == 1 || small)
|
||||||
|
return m_nrv2b;
|
||||||
|
return m_nrv2e;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const int *Packer::getDefaultCompressionMethods_le32(int method, int level, int small) const
|
||||||
|
{
|
||||||
|
static const int m_nrv2b[] = { M_NRV2B_LE32, M_NRV2D_LE32, M_NRV2E_LE32, -1 };
|
||||||
|
static const int m_nrv2d[] = { M_NRV2D_LE32, M_NRV2B_LE32, M_NRV2E_LE32, -1 };
|
||||||
|
static const int m_nrv2e[] = { M_NRV2E_LE32, M_NRV2B_LE32, M_NRV2D_LE32, -1 };
|
||||||
|
|
||||||
|
if (small < 0)
|
||||||
|
small = file_size <= 512*1024;
|
||||||
|
if (M_IS_NRV2B(method))
|
||||||
|
return m_nrv2b;
|
||||||
|
if (M_IS_NRV2D(method))
|
||||||
|
return m_nrv2d;
|
||||||
|
if (M_IS_NRV2E(method))
|
||||||
|
return m_nrv2e;
|
||||||
|
if (level == 1 || small)
|
||||||
|
return m_nrv2b;
|
||||||
|
return m_nrv2e;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// loader util
|
// loader util
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
void Packer::initLoader(const void *pdata, int plen, int pinfo)
|
char const *Packer::getIdentstr(unsigned *size, int small)
|
||||||
{
|
{
|
||||||
delete linker;
|
|
||||||
if (pinfo < 0)
|
|
||||||
pinfo = ~3 & (3 + get_le16(pdata, plen - 2));
|
|
||||||
linker = new Linker(pdata,plen,pinfo);
|
|
||||||
|
|
||||||
static const char identbig[] =
|
static const char identbig[] =
|
||||||
"\n\0"
|
"\n\0"
|
||||||
"$Info: This file is packed with the UPX executable packer http://upx.tsx.org $"
|
"$Info: "
|
||||||
|
"This file is packed with the UPX executable packer http://upx.sf.net $"
|
||||||
"\n\0"
|
"\n\0"
|
||||||
"$Id: UPX " UPX_VERSION_STRING " Copyright (C) 1996-2000 the UPX Team. All Rights Reserved. $"
|
"$Id: UPX "
|
||||||
|
UPX_VERSION_STRING4
|
||||||
|
" Copyright (C) 1996-2002 the UPX Team. All Rights Reserved. $"
|
||||||
"\n";
|
"\n";
|
||||||
|
|
||||||
static const char identsmall[] =
|
static const char identsmall[] =
|
||||||
"\n"
|
"\n"
|
||||||
"$Id: UPX (C) 1996-2000 the UPX Team. All Rights Reserved. http://upx.tsx.org $"
|
"$Id: UPX "
|
||||||
|
"(C) 1996-2002 the UPX Team. All Rights Reserved. http://upx.sf.net $"
|
||||||
"\n";
|
"\n";
|
||||||
|
static const char identtiny[] = UPX_VERSION_STRING4;
|
||||||
|
|
||||||
if (opt->small)
|
if (small < 0)
|
||||||
addSection("IDENTSTR",identsmall,sizeof(identsmall));
|
small = opt->small;
|
||||||
|
if (small >= 2)
|
||||||
|
{
|
||||||
|
*size = sizeof(identtiny);
|
||||||
|
return identtiny;
|
||||||
|
}
|
||||||
|
else if (small >= 1)
|
||||||
|
{
|
||||||
|
*size = sizeof(identsmall);
|
||||||
|
return identsmall;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
addSection("IDENTSTR",identbig,sizeof(identbig));
|
{
|
||||||
|
*size = sizeof(identbig);
|
||||||
|
return identbig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Packer::initLoader(const void *pdata, int plen, int pinfo, int small)
|
||||||
|
{
|
||||||
|
if (pinfo < 0)
|
||||||
|
{
|
||||||
|
pinfo = get_le16((const unsigned char *)pdata + plen - 2);
|
||||||
|
pinfo = (pinfo + 3) &~ 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete linker; linker = NULL;
|
||||||
|
if (getFormat() < 128)
|
||||||
|
linker = new Linker(pdata, plen, pinfo); // little endian
|
||||||
|
else
|
||||||
|
linker = new BeLinker(pdata, plen, pinfo); // big endian
|
||||||
|
|
||||||
|
unsigned size;
|
||||||
|
char const * const ident = getIdentstr(&size, small);
|
||||||
|
linker->addSection("IDENTSTR", ident, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -927,12 +1035,6 @@ void Packer::addLoader(const char *s, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Packer::addSection(const char *sname, const char *sdata, unsigned len)
|
|
||||||
{
|
|
||||||
linker->addSection(sname, sdata, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int Packer::getLoaderSection(const char *name, int *slen) const
|
int Packer::getLoaderSection(const char *name, int *slen) const
|
||||||
{
|
{
|
||||||
int size = -1;
|
int size = -1;
|
||||||
@@ -946,12 +1048,14 @@ int Packer::getLoaderSection(const char *name, int *slen) const
|
|||||||
|
|
||||||
|
|
||||||
// same, but the size of the section may be == 0
|
// same, but the size of the section may be == 0
|
||||||
int Packer::getLoaderSectionStart(const char *name) const
|
int Packer::getLoaderSectionStart(const char *name, int *slen) const
|
||||||
{
|
{
|
||||||
int size = -1;
|
int size = -1;
|
||||||
int ostart = linker->getSection(name, &size);
|
int ostart = linker->getSection(name, &size);
|
||||||
if (ostart < 0 || size < 0)
|
if (ostart < 0 || size < 0)
|
||||||
throwBadLoader();
|
throwBadLoader();
|
||||||
|
if (slen)
|
||||||
|
*slen = size;
|
||||||
return ostart;
|
return ostart;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -982,60 +1086,41 @@ const char *Packer::getDecompressor() const
|
|||||||
"N2BSMA10""N2BDEC10""N2BSMA20""N2BDEC20""N2BSMA30"
|
"N2BSMA10""N2BDEC10""N2BSMA20""N2BDEC20""N2BSMA30"
|
||||||
"N2BDEC30""N2BSMA40""N2BSMA50""N2BDEC50""N2BSMA60"
|
"N2BDEC30""N2BSMA40""N2BSMA50""N2BDEC50""N2BSMA60"
|
||||||
"N2BDEC60";
|
"N2BDEC60";
|
||||||
|
|
||||||
static const char nrv2b_le32_fast[] =
|
static const char nrv2b_le32_fast[] =
|
||||||
"N2BFAS10""+80CXXXX""N2BFAS11""N2BDEC10""N2BFAS20"
|
"N2BFAS10""+80CXXXX""N2BFAS11""N2BDEC10""N2BFAS20"
|
||||||
"N2BDEC20""N2BFAS30""N2BDEC30""N2BFAS40""N2BFAS50"
|
"N2BDEC20""N2BFAS30""N2BDEC30""N2BFAS40""N2BFAS50"
|
||||||
"N2BDEC50""N2BFAS60""+40CXXXX""N2BFAS61""N2BDEC60";
|
"N2BDEC50""N2BFAS60""+40CXXXX""N2BFAS61""N2BDEC60";
|
||||||
|
|
||||||
static const char nrv2d_le32_small[] =
|
static const char nrv2d_le32_small[] =
|
||||||
"N2DSMA10""N2DDEC10""N2DSMA20""N2DDEC20""N2DSMA30"
|
"N2DSMA10""N2DDEC10""N2DSMA20""N2DDEC20""N2DSMA30"
|
||||||
"N2DDEC30""N2DSMA40""N2DSMA50""N2DDEC50""N2DSMA60"
|
"N2DDEC30""N2DSMA40""N2DSMA50""N2DDEC50""N2DSMA60"
|
||||||
"N2DDEC60";
|
"N2DDEC60";
|
||||||
|
|
||||||
static const char nrv2d_le32_fast[] =
|
static const char nrv2d_le32_fast[] =
|
||||||
"N2DFAS10""+80CXXXX""N2DFAS11""N2DDEC10""N2DFAS20"
|
"N2DFAS10""+80CXXXX""N2DFAS11""N2DDEC10""N2DFAS20"
|
||||||
"N2DDEC20""N2DFAS30""N2DDEC30""N2DFAS40""N2DFAS50"
|
"N2DDEC20""N2DFAS30""N2DDEC30""N2DFAS40""N2DFAS50"
|
||||||
"N2DDEC50""N2DFAS60""+40CXXXX""N2DFAS61""N2DDEC60";
|
"N2DDEC50""N2DFAS60""+40CXXXX""N2DFAS61""N2DDEC60";
|
||||||
|
static const char nrv2e_le32_small[] =
|
||||||
|
"N2ESMA10""N2EDEC10""N2ESMA20""N2EDEC20""N2ESMA30"
|
||||||
|
"N2EDEC30""N2ESMA40""N2ESMA50""N2EDEC50""N2ESMA60"
|
||||||
|
"N2EDEC60";
|
||||||
|
static const char nrv2e_le32_fast[] =
|
||||||
|
"N2EFAS10""+80CXXXX""N2EFAS11""N2EDEC10""N2EFAS20"
|
||||||
|
"N2EDEC20""N2EFAS30""N2EDEC30""N2EFAS40""N2EFAS50"
|
||||||
|
"N2EDEC50""N2EFAS60""+40CXXXX""N2EFAS61""N2EDEC60";
|
||||||
|
|
||||||
if (ph.method == M_NRV2B_LE32)
|
if (ph.method == M_NRV2B_LE32)
|
||||||
return opt->small ? nrv2b_le32_small : nrv2b_le32_fast;
|
return opt->small ? nrv2b_le32_small : nrv2b_le32_fast;
|
||||||
if (ph.method == M_NRV2D_LE32)
|
if (ph.method == M_NRV2D_LE32)
|
||||||
return opt->small ? nrv2d_le32_small : nrv2d_le32_fast;
|
return opt->small ? nrv2d_le32_small : nrv2d_le32_fast;
|
||||||
|
if (ph.method == M_NRV2E_LE32)
|
||||||
|
return opt->small ? nrv2e_le32_small : nrv2e_le32_fast;
|
||||||
throwInternalError("bad decompressor");
|
throwInternalError("bad decompressor");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Packer::addFilter32(int filter_id)
|
|
||||||
{
|
|
||||||
assert(filter_id > 0);
|
|
||||||
assert(isValidFilter(filter_id));
|
|
||||||
|
|
||||||
if ((filter_id & 0xf) % 3 == 0)
|
|
||||||
addLoader("CALLTR00",
|
|
||||||
(filter_id > 0x20) ? "CTCLEVE1" : "",
|
|
||||||
"CALLTR01",
|
|
||||||
(filter_id & 0xf) > 3 ? (filter_id > 0x20 ? "CTBSHR01""CTBSWA01" : "CTBROR01""CTBSWA01") : "",
|
|
||||||
"CALLTR02",
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
else
|
|
||||||
addLoader("CALLTR10",
|
|
||||||
(filter_id & 0xf) % 3 == 1 ? "CALLTRE8" : "CALLTRE9",
|
|
||||||
"CALLTR11",
|
|
||||||
(filter_id > 0x20) ? "CTCLEVE2" : "",
|
|
||||||
"CALLTR12",
|
|
||||||
(filter_id & 0xf) > 3 ? (filter_id > 0x20 ? "CTBSHR11""CTBSWA11" : "CTBROR11""CTBSWA11") : "",
|
|
||||||
"CALLTR13",
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// Try compression with several filters, choose the best or first one.
|
// Try compression with several methods and filters, choose the best
|
||||||
// Needs buildLoader().
|
/ or first working one. Needs buildLoader().
|
||||||
//
|
//
|
||||||
// Required inputs:
|
// Required inputs:
|
||||||
// this->ph
|
// this->ph
|
||||||
@@ -1047,23 +1132,23 @@ void Packer::addFilter32(int filter_id)
|
|||||||
//
|
//
|
||||||
// - updates this->ph
|
// - updates this->ph
|
||||||
// - updates *ft
|
// - updates *ft
|
||||||
// - ibuf[] is restored to unfiltered version
|
// - ibuf[] is restored to the original unfiltered version
|
||||||
// - obuf[] contains the best compressed version
|
// - obuf[] contains the best compressed version
|
||||||
//
|
//
|
||||||
// strategy:
|
// strategy:
|
||||||
// 0: try all filters, use best one
|
// n: try the first N filters, use best one
|
||||||
// n: try the first N filters in parm_filters[], use best one
|
|
||||||
// -1: try all filters, use first working one
|
// -1: try all filters, use first working one
|
||||||
// -2: try only the opt->filter filter
|
// -2: try only the opt->filter filter
|
||||||
// -3: use no filter at all
|
// -3: use no filter at all
|
||||||
//
|
//
|
||||||
// This has been prepared for generalization into class Packer so that
|
// This has been prepared for generalization into class Packer so that
|
||||||
// opt->all_filters is available for all executable formats.
|
// opt->all_methods and/or opt->all_filters are available for all
|
||||||
|
// executable formats.
|
||||||
//
|
//
|
||||||
// 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,
|
||||||
@@ -1081,31 +1166,47 @@ 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);
|
||||||
assert(orig_ft.id == 0);
|
assert(orig_ft.id == 0);
|
||||||
assert(filter_off + filter_len <= compress_buf_off + compress_buf_len);
|
assert(filter_off + filter_len <= compress_buf_off + compress_buf_len);
|
||||||
|
|
||||||
// setup raw_filters
|
// setup filter strategy
|
||||||
static const int no_filters[] = { 0, -1 };
|
if (strategy == 0)
|
||||||
int strategy_filters[] = { 0, -1 };
|
{
|
||||||
|
if (opt->all_filters)
|
||||||
|
// choose best from all available filters
|
||||||
|
strategy = INT_MAX;
|
||||||
|
else if (opt->filter >= 0 && isValidFilter(opt->filter))
|
||||||
|
// try opt->filter
|
||||||
|
strategy = -2;
|
||||||
|
else
|
||||||
|
// try the first working filter
|
||||||
|
strategy = -1;
|
||||||
|
}
|
||||||
|
assert(strategy != 0);
|
||||||
|
|
||||||
const int *raw_filters = parm_filters;
|
// setup raw_filters
|
||||||
|
int tmp_filters[] = { 0, -1 };
|
||||||
|
const int *raw_filters = NULL;
|
||||||
|
if (strategy == -3)
|
||||||
|
raw_filters = tmp_filters;
|
||||||
|
else if (strategy == -2 && opt->filter >= 0)
|
||||||
|
{
|
||||||
|
tmp_filters[0] = opt->filter;
|
||||||
|
raw_filters = tmp_filters;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
raw_filters = parm_filters;
|
||||||
if (raw_filters == NULL)
|
if (raw_filters == NULL)
|
||||||
raw_filters = getFilters();
|
raw_filters = getFilters();
|
||||||
if (raw_filters == NULL)
|
if (raw_filters == NULL)
|
||||||
raw_filters = no_filters;
|
raw_filters = tmp_filters;
|
||||||
if (strategy == -2)
|
|
||||||
{
|
|
||||||
assert(opt->filter >= 0);
|
|
||||||
strategy_filters[0] = opt->filter;
|
|
||||||
raw_filters = strategy_filters;
|
|
||||||
}
|
}
|
||||||
else if (strategy == -3)
|
|
||||||
raw_filters = no_filters;
|
|
||||||
|
|
||||||
// first pass - count number of filters
|
// first pass - count number of filters
|
||||||
int raw_nfilters = 0;
|
int raw_nfilters = 0;
|
||||||
@@ -1115,56 +1216,63 @@ void Packer::compressWithFilters(Filter *parm_ft, unsigned *parm_overlapoh,
|
|||||||
raw_nfilters++;
|
raw_nfilters++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy filters, eliminate duplicates, add a 0
|
// copy filters, add a 0
|
||||||
int nfilters = 0;
|
int nfilters = 0;
|
||||||
bool zero_seen = false;
|
bool zero_seen = false;
|
||||||
autoheap_array(int, filters, raw_nfilters + 2);
|
Array(int, filters, raw_nfilters + 2);
|
||||||
for (f = raw_filters; *f >= 0; f++)
|
for (f = raw_filters; *f >= 0; f++)
|
||||||
{
|
{
|
||||||
if (*f == 0)
|
if (*f == 0)
|
||||||
zero_seen = true;
|
zero_seen = true;
|
||||||
bool duplicate = false;
|
|
||||||
for (int i = 0; i < nfilters; i++)
|
|
||||||
if (filters[i] == *f)
|
|
||||||
duplicate = true;
|
|
||||||
if (!duplicate)
|
|
||||||
filters[nfilters++] = *f;
|
filters[nfilters++] = *f;
|
||||||
|
if (nfilters == strategy)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (!zero_seen)
|
if (!zero_seen)
|
||||||
filters[nfilters++] = 0;
|
filters[nfilters++] = 0;
|
||||||
filters[nfilters] = -1;
|
filters[nfilters] = -1;
|
||||||
|
|
||||||
|
// methods
|
||||||
|
int tmp_methods[] = { ph.method, -1 };
|
||||||
|
const int *methods = NULL;
|
||||||
|
if (opt->all_methods)
|
||||||
|
methods = getCompressionMethods(-1, ph.level);
|
||||||
|
if (methods == NULL)
|
||||||
|
methods = tmp_methods;
|
||||||
|
int nmethods = 0;
|
||||||
|
while (methods[nmethods] >= 0)
|
||||||
|
{
|
||||||
|
assert(isValidCompressionMethod(methods[nmethods]));
|
||||||
|
nmethods++;
|
||||||
|
}
|
||||||
|
assert(nmethods > 0);
|
||||||
|
|
||||||
// update total_passes
|
// update total_passes
|
||||||
if (strategy < 0)
|
if (strategy < 0)
|
||||||
ui_total_passes += 1;
|
ui_total_passes += 1 * nmethods;
|
||||||
else
|
else
|
||||||
{
|
ui_total_passes += nfilters * nmethods;
|
||||||
if (strategy > nfilters)
|
|
||||||
nfilters = strategy;
|
|
||||||
ui_total_passes += nfilters;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Working buffer for compressed data. Don't waste memory.
|
// Working buffer for compressed data. Don't waste memory.
|
||||||
upx_byte *otemp = obuf;
|
upx_byte *otemp = obuf;
|
||||||
MemBuffer otemp_buf;
|
MemBuffer otemp_buf;
|
||||||
if (nfilters > 1 && strategy >= 0)
|
|
||||||
{
|
|
||||||
otemp_buf.allocForCompression(compress_buf_len);
|
|
||||||
otemp = otemp_buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
// compress
|
// compress
|
||||||
int nfilters_success = 0;
|
int nfilters_success = 0;
|
||||||
for (int i = 0; i < nfilters; i++)
|
for (int m = 0; m < nmethods; m++) // for all methods
|
||||||
|
{
|
||||||
|
for (int i = 0; i < nfilters; i++) // for all filters
|
||||||
{
|
{
|
||||||
// get fresh packheader
|
// get fresh packheader
|
||||||
ph = orig_ph;
|
ph = orig_ph;
|
||||||
|
ph.method = methods[m];
|
||||||
ph.filter = filters[i];
|
ph.filter = filters[i];
|
||||||
// get fresh filter
|
// get fresh filter
|
||||||
Filter ft = orig_ft;
|
Filter ft = orig_ft;
|
||||||
ft.init(filters[i], orig_ft.addvalue);
|
ft.init(ph.filter, orig_ft.addvalue);
|
||||||
// filter
|
// filter
|
||||||
optimizeFilter(&ft, ibuf + filter_off, filter_len);
|
optimizeFilter(&ft, ibuf + filter_off, filter_len);
|
||||||
|
|
||||||
bool success = ft.filter(ibuf + filter_off, filter_len);
|
bool success = ft.filter(ibuf + filter_off, filter_len);
|
||||||
if (ft.id != 0 && ft.calls == 0)
|
if (ft.id != 0 && ft.calls == 0)
|
||||||
{
|
{
|
||||||
@@ -1173,25 +1281,59 @@ void Packer::compressWithFilters(Filter *parm_ft, unsigned *parm_overlapoh,
|
|||||||
}
|
}
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
// filter failed or was usesless
|
// filter failed or was useless
|
||||||
if (strategy >= 0)
|
if (strategy > 0)
|
||||||
ui_total_passes -= 1;
|
{
|
||||||
|
// adjust passes
|
||||||
|
if (ui_pass >= 0)
|
||||||
|
ui_pass++;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// filter success
|
// filter success
|
||||||
|
#if 0
|
||||||
|
printf("filter: id 0x%02x size %6d, calls %5d/%5d/%3d/%5d/%5d, cto 0x%02x\n",
|
||||||
|
ft.id, ft.buf_len, ft.calls, ft.noncalls, ft.wrongcalls, ft.firstcall, ft.lastcall, ft.cto);
|
||||||
|
#endif
|
||||||
|
if (nfilters_success > 0 && otemp == obuf)
|
||||||
|
{
|
||||||
|
otemp_buf.allocForCompression(compress_buf_len);
|
||||||
|
otemp = otemp_buf;
|
||||||
|
}
|
||||||
nfilters_success++;
|
nfilters_success++;
|
||||||
ph.filter_cto = ft.cto;
|
ph.filter_cto = ft.cto;
|
||||||
|
ph.n_mru = ft.n_mru;
|
||||||
// compress
|
// compress
|
||||||
if (compress(ibuf + compress_buf_off, otemp, max_offset, max_match))
|
if (compress(ibuf + compress_buf_off, otemp, max_offset, max_match))
|
||||||
|
{
|
||||||
|
unsigned lsize = 0;
|
||||||
|
if (ph.c_len + lsize < best_ph.c_len + best_ph_lsize)
|
||||||
{
|
{
|
||||||
// get results
|
// get results
|
||||||
const unsigned lsize = buildLoader(&ft);
|
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%2d %02x: %d +%4d = %d (best: %d +%4d = %d)\n", ph.method, ph.filter,
|
||||||
ph.c_len, getLoaderSize(), ph.c_len + getLoaderSize(),
|
ph.c_len, lsize, ph.c_len + lsize,
|
||||||
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)
|
||||||
|
{
|
||||||
|
// prefer smaller loaders
|
||||||
|
if (lsize < best_ph_lsize)
|
||||||
|
update = true;
|
||||||
|
else if (lsize == best_ph_lsize)
|
||||||
|
{
|
||||||
|
// prefer less overlap_overhead
|
||||||
|
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)
|
||||||
@@ -1200,7 +1342,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
|
||||||
@@ -1209,17 +1350,18 @@ void Packer::compressWithFilters(Filter *parm_ft, unsigned *parm_overlapoh,
|
|||||||
if (strategy < 0)
|
if (strategy < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// postconditions
|
// postconditions 1)
|
||||||
assert(nfilters_success > 0);
|
assert(nfilters_success > 0);
|
||||||
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);
|
||||||
|
// FIXME assert(best_ph.n_mru == best_ft.n_mru);
|
||||||
|
|
||||||
// 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)
|
||||||
@@ -1227,89 +1369,14 @@ void Packer::compressWithFilters(Filter *parm_ft, unsigned *parm_overlapoh,
|
|||||||
if (!checkCompressionRatio(best_ph.u_len, best_ph.c_len))
|
if (!checkCompressionRatio(best_ph.u_len, best_ph.c_len))
|
||||||
throwNotCompressible();
|
throwNotCompressible();
|
||||||
|
|
||||||
|
// postconditions 2)
|
||||||
|
assert(best_ph.overlap_overhead > 0);
|
||||||
|
|
||||||
// convenience
|
// convenience
|
||||||
buildLoader(&best_ft);
|
buildLoader(&best_ft);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
// filter util
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
bool Packer::isValidFilter(int filter_id) const
|
|
||||||
{
|
|
||||||
if (filter_id == 0)
|
|
||||||
return true;
|
|
||||||
for (const int *f = getFilters(); f && *f >= 0; f++)
|
|
||||||
{
|
|
||||||
if (*f == filter_id)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Packer::tryFilters(Filter *ft, upx_byte *buf, unsigned buf_len,
|
|
||||||
unsigned addvalue) const
|
|
||||||
{
|
|
||||||
// debug
|
|
||||||
//scanFilters(ft, buf, buf_len, addvalue);
|
|
||||||
|
|
||||||
ft->init();
|
|
||||||
if (opt->filter == 0)
|
|
||||||
return;
|
|
||||||
for (const int *f = getFilters(); f && *f >= 0; f++)
|
|
||||||
{
|
|
||||||
if (*f == 0) // skip no-filter
|
|
||||||
continue;
|
|
||||||
if (opt->filter < 0 || *f == opt->filter)
|
|
||||||
{
|
|
||||||
ft->init(*f, addvalue);
|
|
||||||
optimizeFilter(ft, buf, buf_len);
|
|
||||||
if (ft->filter(buf, buf_len) && ft->calls > 0)
|
|
||||||
break; // success
|
|
||||||
ft->init();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Packer::scanFilters(Filter *ft, const upx_byte *buf, unsigned buf_len,
|
|
||||||
unsigned addvalue) const
|
|
||||||
{
|
|
||||||
ft->init();
|
|
||||||
if (opt->filter == 0)
|
|
||||||
return;
|
|
||||||
for (const int *f = getFilters(); f && *f >= 0; f++)
|
|
||||||
{
|
|
||||||
if (*f == 0) // skip no-filter
|
|
||||||
continue;
|
|
||||||
ft->init(*f, addvalue);
|
|
||||||
//static const int ctos[] = { 0xff, 0xfe, 0x80, 0x22, -1 };
|
|
||||||
//ft->preferred_ctos = ctos;
|
|
||||||
if (ft->scan(buf, buf_len))
|
|
||||||
{
|
|
||||||
printf("scanFilters: id 0x%02x size: %6d: calls %5d/%5d/%3d, cto 0x%02x\n",
|
|
||||||
ft->id, ft->buf_len, ft->calls, ft->noncalls, ft->wrongcalls, ft->cto);
|
|
||||||
}
|
|
||||||
ft->init();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Packer::patchFilter32(void *loader, int lsize, const Filter *ft)
|
|
||||||
{
|
|
||||||
if (ft->id == 0)
|
|
||||||
return false;
|
|
||||||
assert(ft->calls > 0);
|
|
||||||
if (ft->id > 0x20)
|
|
||||||
patch_le16(loader, lsize, "??", '?' + (ft->cto << 8));
|
|
||||||
patch_le32(loader, lsize, "TEXL", (ft->id & 0xf) % 3 == 0 ? ft->calls :
|
|
||||||
ft->lastcall - ft->calls * 4);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
vi:ts=4:et:nowrap
|
vi:ts=4:et:nowrap
|
||||||
*/
|
*/
|
||||||
|
|||||||
+31
-17
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// fields stored in compressed file
|
// fields stored in compressed file
|
||||||
unsigned magic; // UPX_MAGIC_LE32
|
//enum { magic = UPX_MAGIC_LE32 };
|
||||||
int version;
|
int version;
|
||||||
int format; // executable format
|
int format; // executable format
|
||||||
int method; // compresison method
|
int method; // compresison method
|
||||||
@@ -73,8 +73,13 @@ public:
|
|||||||
off_t u_file_size;
|
off_t u_file_size;
|
||||||
int filter;
|
int filter;
|
||||||
int filter_cto;
|
int filter_cto;
|
||||||
|
int n_mru; // FIXME: rename to filter_misc
|
||||||
int header_checksum;
|
int header_checksum;
|
||||||
|
|
||||||
|
// support fields for verifying decompression
|
||||||
|
unsigned saved_u_adler;
|
||||||
|
unsigned saved_c_adler;
|
||||||
|
|
||||||
// info fields set by fillPackHeader()
|
// info fields set by fillPackHeader()
|
||||||
long buf_offset;
|
long buf_offset;
|
||||||
|
|
||||||
@@ -87,6 +92,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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -107,7 +115,7 @@ public:
|
|||||||
// A unique integer ID for this executable format. See conf.h.
|
// A unique integer ID for this executable format. See conf.h.
|
||||||
virtual int getFormat() const = 0;
|
virtual int getFormat() const = 0;
|
||||||
virtual const char *getName() const = 0;
|
virtual const char *getName() const = 0;
|
||||||
virtual int getCompressionMethod() const = 0;
|
virtual const int *getCompressionMethods(int method, int level) const = 0;
|
||||||
virtual const int *getFilters() const = 0;
|
virtual const int *getFilters() const = 0;
|
||||||
|
|
||||||
// PackMaster entries
|
// PackMaster entries
|
||||||
@@ -158,32 +166,33 @@ 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 = 0,
|
||||||
|
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();
|
||||||
unsigned overlap_overhead);
|
|
||||||
|
|
||||||
|
|
||||||
// packheader handling
|
// packheader handling
|
||||||
virtual int patchPackHeader(void *b, int blen);
|
virtual int patchPackHeader(void *b, int blen);
|
||||||
virtual bool getPackHeader(void *b, int blen);
|
virtual bool getPackHeader(void *b, int blen);
|
||||||
virtual bool readPackHeader(int len);
|
virtual bool readPackHeader(int len);
|
||||||
|
virtual void checkAlreadyPacked(void *b, int blen);
|
||||||
|
|
||||||
// filter handling
|
// filter handling [see packerf.cpp]
|
||||||
virtual bool isValidFilter(int filter_id) const;
|
virtual bool isValidFilter(int filter_id) const;
|
||||||
virtual void tryFilters(Filter *ft, upx_byte *buf, unsigned buf_len,
|
virtual void tryFilters(Filter *ft, upx_byte *buf, unsigned buf_len,
|
||||||
unsigned addvalue=0) const;
|
unsigned addvalue=0) const;
|
||||||
@@ -191,19 +200,19 @@ protected:
|
|||||||
unsigned addvalue=0) const;
|
unsigned addvalue=0) const;
|
||||||
virtual void optimizeFilter(Filter *, const upx_byte *, unsigned) const
|
virtual void optimizeFilter(Filter *, const upx_byte *, unsigned) const
|
||||||
{ }
|
{ }
|
||||||
|
virtual void addFilter32(int filter_id);
|
||||||
virtual bool patchFilter32(void *, int, const Filter *ft);
|
virtual bool patchFilter32(void *, int, const Filter *ft);
|
||||||
|
|
||||||
// loader util
|
// loader util
|
||||||
virtual int buildLoader(const Filter *) { return getLoaderSize(); }
|
virtual int buildLoader(const Filter *) { return getLoaderSize(); }
|
||||||
virtual const upx_byte *getLoader() const;
|
virtual const upx_byte *getLoader() const;
|
||||||
virtual int getLoaderSize() const;
|
virtual int getLoaderSize() const;
|
||||||
virtual void initLoader(const void *pdata, int plen, int pinfo=-1);
|
virtual void initLoader(const void *pdata, int plen, int pinfo=-1, int small=-1);
|
||||||
virtual void addLoader(const char *s, ...);
|
virtual void addLoader(const char *s, ...);
|
||||||
virtual void addSection(const char *sname, const char *sdata, unsigned len);
|
|
||||||
virtual int getLoaderSection(const char *name, int *slen=NULL) const;
|
virtual int getLoaderSection(const char *name, int *slen=NULL) const;
|
||||||
virtual int getLoaderSectionStart(const char *name) const;
|
virtual int getLoaderSectionStart(const char *name, int *slen=NULL) const;
|
||||||
virtual void addFilter32(int filter_id);
|
|
||||||
virtual const char *getDecompressor() const;
|
virtual const char *getDecompressor() const;
|
||||||
|
virtual const char *getIdentstr(unsigned *size, int small=-1);
|
||||||
|
|
||||||
// stub and overlay util
|
// stub and overlay util
|
||||||
static void handleStub(InputFile *fi, OutputFile *fo, long size);
|
static void handleStub(InputFile *fi, OutputFile *fo, long size);
|
||||||
@@ -230,6 +239,11 @@ protected:
|
|||||||
virtual upx_byte *optimizeReloc32(upx_byte *in,unsigned relocnum,upx_byte *out,upx_byte *image,int bs,int *big);
|
virtual upx_byte *optimizeReloc32(upx_byte *in,unsigned relocnum,upx_byte *out,upx_byte *image,int bs,int *big);
|
||||||
virtual unsigned unoptimizeReloc32(upx_byte **in,upx_byte *image,MemBuffer *out,int bs);
|
virtual unsigned unoptimizeReloc32(upx_byte **in,upx_byte *image,MemBuffer *out,int bs);
|
||||||
|
|
||||||
|
// compression method util
|
||||||
|
const int *getDefaultCompressionMethods_8(int method, int level, int small=-1) const;
|
||||||
|
const int *getDefaultCompressionMethods_le32(int method, int level, int small=-1) const;
|
||||||
|
public:
|
||||||
|
static bool isValidCompressionMethod(int method);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
InputFile *fi;
|
InputFile *fi;
|
||||||
@@ -247,7 +261,7 @@ protected:
|
|||||||
int ui_pass;
|
int ui_pass;
|
||||||
int ui_total_passes;
|
int ui_total_passes;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
// linker
|
// linker
|
||||||
Linker *linker;
|
Linker *linker;
|
||||||
|
|
||||||
|
|||||||
+401
@@ -0,0 +1,401 @@
|
|||||||
|
/* packerf.cpp -- packer filter handling
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "conf.h"
|
||||||
|
#include "packer.h"
|
||||||
|
#include "filter.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// filter util
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
bool Packer::isValidFilter(int filter_id) const
|
||||||
|
{
|
||||||
|
if (!Filter::isValidFilter(filter_id))
|
||||||
|
return false;
|
||||||
|
if (filter_id == 0)
|
||||||
|
return true;
|
||||||
|
for (const int *f = getFilters(); f && *f >= 0; f++)
|
||||||
|
{
|
||||||
|
if (*f == filter_id)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Packer::tryFilters(Filter *ft, upx_byte *buf, unsigned buf_len,
|
||||||
|
unsigned addvalue) const
|
||||||
|
{
|
||||||
|
// debug
|
||||||
|
//scanFilters(ft, buf, buf_len, addvalue);
|
||||||
|
|
||||||
|
ft->init();
|
||||||
|
if (opt->filter == 0)
|
||||||
|
return;
|
||||||
|
for (const int *f = getFilters(); f && *f >= 0; f++)
|
||||||
|
{
|
||||||
|
if (*f == 0) // skip no-filter
|
||||||
|
continue;
|
||||||
|
if (opt->filter < 0 || *f == opt->filter)
|
||||||
|
{
|
||||||
|
ft->init(*f, addvalue);
|
||||||
|
optimizeFilter(ft, buf, buf_len);
|
||||||
|
if (ft->filter(buf, buf_len) && ft->calls > 0)
|
||||||
|
break; // success
|
||||||
|
ft->init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Packer::scanFilters(Filter *ft, const upx_byte *buf, unsigned buf_len,
|
||||||
|
unsigned addvalue) const
|
||||||
|
{
|
||||||
|
ft->init();
|
||||||
|
if (opt->filter == 0)
|
||||||
|
return;
|
||||||
|
for (const int *f = getFilters(); f && *f >= 0; f++)
|
||||||
|
{
|
||||||
|
if (*f == 0) // skip no-filter
|
||||||
|
continue;
|
||||||
|
ft->init(*f, addvalue);
|
||||||
|
//static const int ctos[] = { 0xff, 0xfe, 0x80, 0x22, -1 };
|
||||||
|
//ft->preferred_ctos = ctos;
|
||||||
|
if (ft->scan(buf, buf_len))
|
||||||
|
{
|
||||||
|
printf("scanFilters: id 0x%02x size: %6d: calls %5d/%5d/%3d, cto 0x%02x\n",
|
||||||
|
ft->id, ft->buf_len, ft->calls, ft->noncalls, ft->wrongcalls, ft->cto);
|
||||||
|
}
|
||||||
|
ft->init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// addFilter32
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#define NOFILT 0 // no filter
|
||||||
|
#define FNOMRU 1 // filter, but not using mru
|
||||||
|
#define MRUFLT 2 // mru filter
|
||||||
|
|
||||||
|
static inline unsigned f80_call(int fid)
|
||||||
|
{
|
||||||
|
return (1+ (0x0f & fid)) % 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned f80_jmp1(int fid)
|
||||||
|
{
|
||||||
|
return ((1+ (0x0f & fid)) / 3) % 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned f80_jcc2(int fid)
|
||||||
|
{
|
||||||
|
return f80_jmp1(fid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Packer::addFilter32(int filter_id)
|
||||||
|
{
|
||||||
|
assert(filter_id > 0);
|
||||||
|
assert(isValidFilter(filter_id));
|
||||||
|
|
||||||
|
if (filter_id < 0x80) {
|
||||||
|
if ((filter_id & 0xf) % 3 == 0) {
|
||||||
|
if (filter_id < 0x40) {
|
||||||
|
addLoader("CALLTR00",
|
||||||
|
(filter_id > 0x20) ? "CTCLEVE1" : "",
|
||||||
|
"CALLTR01",
|
||||||
|
(filter_id & 0xf) > 3 ? (filter_id > 0x20 ? "CTBSHR01""CTBSWA01" : "CTBROR01""CTBSWA01") : "",
|
||||||
|
"CALLTR02",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (0x40==(0xF0 & filter_id)) {
|
||||||
|
addLoader("CKLLTR00", 0);
|
||||||
|
if (9<=(0xf & filter_id)) {
|
||||||
|
addLoader("CKLLTR10", 0);
|
||||||
|
}
|
||||||
|
addLoader("CKLLTR20", 0);
|
||||||
|
if (9<=(0xf & filter_id)) {
|
||||||
|
addLoader("CKLLTR30", 0);
|
||||||
|
}
|
||||||
|
addLoader("CKLLTR40", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
addLoader("CALLTR10",
|
||||||
|
(filter_id & 0xf) % 3 == 1 ? "CALLTRE8" : "CALLTRE9",
|
||||||
|
"CALLTR11",
|
||||||
|
(filter_id > 0x20) ? "CTCLEVE2" : "",
|
||||||
|
"CALLTR12",
|
||||||
|
(filter_id & 0xf) > 3 ? (filter_id > 0x20 ? "CTBSHR11""CTBSWA11" : "CTBROR11""CTBSWA11") : "",
|
||||||
|
"CALLTR13",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (0x80==(filter_id & 0xF0)) {
|
||||||
|
bool const x386 = (opt->cpu <= opt->CPU_386);
|
||||||
|
unsigned const n_mru = ph.n_mru ? 1+ ph.n_mru : 0;
|
||||||
|
bool const mrupwr2 = (0!=n_mru) && 0==((n_mru -1) & n_mru);
|
||||||
|
unsigned const f_call = f80_call(filter_id);
|
||||||
|
unsigned const f_jmp1 = f80_jmp1(filter_id);
|
||||||
|
unsigned const f_jcc2 = f80_jcc2(filter_id);
|
||||||
|
|
||||||
|
if (NOFILT!=f_jcc2) {
|
||||||
|
addLoader("LXJCC010", 0);
|
||||||
|
if (n_mru) {
|
||||||
|
addLoader("LXMRU045", 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addLoader("LXMRU046", 0);
|
||||||
|
}
|
||||||
|
if (0==n_mru || MRUFLT!=f_jcc2) {
|
||||||
|
addLoader("LXJCC020", 0);
|
||||||
|
}
|
||||||
|
else { // 0!=n_mru
|
||||||
|
addLoader("LXJCC021", 0);
|
||||||
|
}
|
||||||
|
if (NOFILT!=f_jcc2) {
|
||||||
|
addLoader("LXJCC023", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addLoader("LXUNF037", 0);
|
||||||
|
if (x386) {
|
||||||
|
if (n_mru) {
|
||||||
|
addLoader("LXUNF386", 0);
|
||||||
|
}
|
||||||
|
addLoader("LXUNF387", 0);
|
||||||
|
if (n_mru) {
|
||||||
|
addLoader("LXUNF388", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addLoader("LXUNF486", 0);
|
||||||
|
if (n_mru) {
|
||||||
|
addLoader("LXUNF487", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (n_mru) {
|
||||||
|
addLoader("LXMRU065", 0);
|
||||||
|
if (256==n_mru) {
|
||||||
|
addLoader("MRUBYTE3", 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addLoader("MRUARB30", 0);
|
||||||
|
if (mrupwr2) {
|
||||||
|
addLoader("MRUBITS3", 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addLoader("MRUARB40", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addLoader("LXMRU070", 0);
|
||||||
|
if (256==n_mru) {
|
||||||
|
addLoader("MRUBYTE4", 0);
|
||||||
|
}
|
||||||
|
else if (mrupwr2) {
|
||||||
|
addLoader("MRUBITS4", 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addLoader("MRUARB50", 0);
|
||||||
|
}
|
||||||
|
addLoader("LXMRU080", 0);
|
||||||
|
if (256==n_mru) {
|
||||||
|
addLoader("MRUBYTE5", 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addLoader("MRUARB60", 0);
|
||||||
|
if (mrupwr2) {
|
||||||
|
addLoader("MRUBITS5", 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addLoader("MRUARB70", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addLoader("LXMRU090", 0);
|
||||||
|
if (256==n_mru) {
|
||||||
|
addLoader("MRUBYTE6", 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addLoader("MRUARB80", 0);
|
||||||
|
if (mrupwr2) {
|
||||||
|
addLoader("MRUBITS6", 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addLoader("MRUARB90", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addLoader("LXMRU100", 0);
|
||||||
|
}
|
||||||
|
addLoader("LXUNF040", 0);
|
||||||
|
if (n_mru) {
|
||||||
|
addLoader("LXMRU110", 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addLoader("LXMRU111", 0);
|
||||||
|
}
|
||||||
|
addLoader("LXUNF041", 0);
|
||||||
|
addLoader("LXUNF042", 0);
|
||||||
|
if (n_mru) {
|
||||||
|
addLoader("LXMRU010", 0);
|
||||||
|
if (NOFILT!=f_jmp1 && NOFILT==f_call) {
|
||||||
|
addLoader("LXJMPA00", 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addLoader("LXCALLB0", 0);
|
||||||
|
}
|
||||||
|
addLoader("LXUNF021", 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addLoader("LXMRU022", 0);
|
||||||
|
if (NOFILT!=f_jmp1 && NOFILT==f_call) {
|
||||||
|
addLoader("LXJMPA01", 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addLoader("LXCALLB1", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (n_mru) {
|
||||||
|
if (256!=n_mru && mrupwr2) {
|
||||||
|
addLoader("MRUBITS1", 0);
|
||||||
|
}
|
||||||
|
addLoader("LXMRU030", 0);
|
||||||
|
if (256==n_mru) {
|
||||||
|
addLoader("MRUBYTE1", 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addLoader("MRUARB10", 0);
|
||||||
|
}
|
||||||
|
addLoader("LXMRU040", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
addLoader("LXUNF030", 0);
|
||||||
|
if (NOFILT!=f_jcc2) {
|
||||||
|
addLoader("LXJCC000", 0);
|
||||||
|
}
|
||||||
|
if (NOFILT!=f_call || NOFILT!=f_jmp1) { // at least one is filtered
|
||||||
|
// shift opcode origin to zero
|
||||||
|
if (0==n_mru) {
|
||||||
|
addLoader("LXCJ0MRU", 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addLoader("LXCJ1MRU", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine if in range
|
||||||
|
if ((NOFILT!=f_call) && (NOFILT!=f_jmp1)) { // unfilter both
|
||||||
|
addLoader("LXCALJMP", 0);
|
||||||
|
}
|
||||||
|
if ((NOFILT==f_call) ^ (NOFILT==f_jmp1)) { // unfilter just one
|
||||||
|
if (0==n_mru) {
|
||||||
|
addLoader("LXCALL00", 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addLoader("LXCALL01", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine if mru applies
|
||||||
|
if (0==n_mru || ! ((FNOMRU==f_call) || (FNOMRU==f_jmp1)) ) {
|
||||||
|
addLoader("LXCJ2MRU", 0); // no mru, or no exceptions
|
||||||
|
}
|
||||||
|
else { // mru on one, but not the other
|
||||||
|
addLoader("LXCJ4MRU", 0);
|
||||||
|
if (MRUFLT==f_jmp1) { // JMP only
|
||||||
|
addLoader("LXCJ6MRU", 0);
|
||||||
|
} else
|
||||||
|
if (MRUFLT==f_call) { // CALL only
|
||||||
|
addLoader("LXCJ7MRU", 0);
|
||||||
|
}
|
||||||
|
addLoader("LXCJ8MRU", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addLoader("LXUNF034", 0);
|
||||||
|
if (n_mru) {
|
||||||
|
addLoader("LXMRU055", 0);
|
||||||
|
if (256==n_mru) {
|
||||||
|
addLoader("MRUBYTE2", 0);
|
||||||
|
}
|
||||||
|
else if (mrupwr2) {
|
||||||
|
addLoader("MRUBITS2", 0);
|
||||||
|
}
|
||||||
|
else if (n_mru) {
|
||||||
|
addLoader("MRUARB20", 0);
|
||||||
|
}
|
||||||
|
addLoader("LXMRU057", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef NOFILT
|
||||||
|
#undef FNOMRU
|
||||||
|
#undef MRUFLT
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// patchFilter32
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
bool Packer::patchFilter32(void *loader, int lsize, const Filter *ft)
|
||||||
|
{
|
||||||
|
if (ft->id == 0)
|
||||||
|
return false;
|
||||||
|
assert(ft->calls > 0);
|
||||||
|
|
||||||
|
if (ft->id < 0x80) {
|
||||||
|
if (0x40 <= ft->id && ft->id < 0x50 && UPX_F_LINUX_i386==ph.format) {
|
||||||
|
// "push byte '?'"
|
||||||
|
patch_le16(loader, lsize, "\x6a?", 0x6a + (ft->cto << 8));
|
||||||
|
}
|
||||||
|
if (0x20 <= ft->id && ft->id < 0x40) {
|
||||||
|
// 077==modr/m of "cmp [edi], byte '?'" (compare immediate 8 bits)
|
||||||
|
patch_le16(loader, lsize, "\077?", 077 + (ft->cto << 8));
|
||||||
|
}
|
||||||
|
if (ft->id < 0x40) {
|
||||||
|
patch_le32(loader, lsize, "TEXL", (ft->id & 0xf) % 3 == 0 ? ft->calls :
|
||||||
|
ft->lastcall - ft->calls * 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (0x80==(ft->id & 0xF0)) {
|
||||||
|
int const mru = ph.n_mru ? 1+ ph.n_mru : 0;
|
||||||
|
if (mru && mru!=256) {
|
||||||
|
unsigned const is_pwr2 = (0==((mru -1) & mru));
|
||||||
|
patch_le32(0x80 + (char *)loader, lsize - 0x80, "NMRU", mru - is_pwr2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
vi:ts=4:et:nowrap
|
||||||
|
*/
|
||||||
|
|
||||||
+49
-16
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ int PackHeader::getPackHeaderSize() const
|
|||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
// see stub/header.ash
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
void PackHeader::putPackHeader(upx_bytep p)
|
void PackHeader::putPackHeader(upx_bytep p)
|
||||||
@@ -108,42 +108,57 @@ void PackHeader::putPackHeader(upx_bytep p)
|
|||||||
throwBadLoader();
|
throwBadLoader();
|
||||||
#else
|
#else
|
||||||
assert(get_le32(p) == UPX_MAGIC_LE32);
|
assert(get_le32(p) == UPX_MAGIC_LE32);
|
||||||
|
if (get_le32(p+4) != UPX_MAGIC2_LE32)
|
||||||
|
{
|
||||||
|
//fprintf(stderr, "MAGIC2_LE32: %x %x\n", get_le32(p+4), UPX_MAGIC2_LE32);
|
||||||
|
throwBadLoader();
|
||||||
|
}
|
||||||
|
|
||||||
p[4] = (unsigned char) version;
|
int size = 0;
|
||||||
p[5] = (unsigned char) format;
|
int old_chksum = 0;
|
||||||
p[6] = (unsigned char) method;
|
|
||||||
p[7] = (unsigned char) level;
|
|
||||||
|
|
||||||
// the new variable length header
|
// the new variable length header
|
||||||
if (format < 128)
|
if (format < 128)
|
||||||
{
|
{
|
||||||
set_le32(p+8,u_adler);
|
|
||||||
set_le32(p+12,c_adler);
|
|
||||||
if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS)
|
if (format == UPX_F_DOS_COM || format == UPX_F_DOS_SYS)
|
||||||
{
|
{
|
||||||
|
size = 22;
|
||||||
|
old_chksum = get_packheader_checksum(p, size - 1);
|
||||||
set_le16(p+16,u_len);
|
set_le16(p+16,u_len);
|
||||||
set_le16(p+18,c_len);
|
set_le16(p+18,c_len);
|
||||||
p[20] = (unsigned char) filter;
|
p[20] = (unsigned char) filter;
|
||||||
}
|
}
|
||||||
else if (format == UPX_F_DOS_EXE || format == UPX_F_DOS_EXEH)
|
else if (format == UPX_F_DOS_EXE)
|
||||||
{
|
{
|
||||||
|
size = 27;
|
||||||
|
old_chksum = get_packheader_checksum(p, size - 1);
|
||||||
set_le24(p+16,u_len);
|
set_le24(p+16,u_len);
|
||||||
set_le24(p+19,c_len);
|
set_le24(p+19,c_len);
|
||||||
set_le24(p+22,u_file_size);
|
set_le24(p+22,u_file_size);
|
||||||
p[25] = (unsigned char) filter;
|
p[25] = (unsigned char) filter;
|
||||||
}
|
}
|
||||||
|
else if (format == UPX_F_DOS_EXEH)
|
||||||
|
{
|
||||||
|
throwInternalError("invalid format");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
size = 32;
|
||||||
|
old_chksum = get_packheader_checksum(p, size - 1);
|
||||||
set_le32(p+16,u_len);
|
set_le32(p+16,u_len);
|
||||||
set_le32(p+20,c_len);
|
set_le32(p+20,c_len);
|
||||||
set_le32(p+24,u_file_size);
|
set_le32(p+24,u_file_size);
|
||||||
p[28] = (unsigned char) filter;
|
p[28] = (unsigned char) filter;
|
||||||
p[29] = (unsigned char) filter_cto;
|
p[29] = (unsigned char) filter_cto;
|
||||||
p[30] = 0;
|
p[30] = (unsigned char) (n_mru ? 0 : n_mru -1);
|
||||||
}
|
}
|
||||||
|
set_le32(p+8,u_adler);
|
||||||
|
set_le32(p+12,c_adler);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
size = 32;
|
||||||
|
old_chksum = get_packheader_checksum(p, size - 1);
|
||||||
set_be32(p+8,u_len);
|
set_be32(p+8,u_len);
|
||||||
set_be32(p+12,c_len);
|
set_be32(p+12,c_len);
|
||||||
set_be32(p+16,u_adler);
|
set_be32(p+16,u_adler);
|
||||||
@@ -151,11 +166,27 @@ void PackHeader::putPackHeader(upx_bytep p)
|
|||||||
set_be32(p+24,u_file_size);
|
set_be32(p+24,u_file_size);
|
||||||
p[28] = (unsigned char) filter;
|
p[28] = (unsigned char) filter;
|
||||||
p[29] = (unsigned char) filter_cto;
|
p[29] = (unsigned char) filter_cto;
|
||||||
p[30] = 0;
|
p[30] = (unsigned char) (n_mru ? 0 : n_mru -1);
|
||||||
|
size = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
// store header_checksum
|
p[4] = (unsigned char) version;
|
||||||
const int size = getPackHeaderSize();
|
p[5] = (unsigned char) format;
|
||||||
|
p[6] = (unsigned char) method;
|
||||||
|
p[7] = (unsigned char) level;
|
||||||
|
|
||||||
|
// header_checksum
|
||||||
|
assert(size == getPackHeaderSize());
|
||||||
|
// check old header_checksum
|
||||||
|
if (p[size - 1] != 0)
|
||||||
|
{
|
||||||
|
if (p[size - 1] != old_chksum)
|
||||||
|
{
|
||||||
|
//printf("old_checksum: %d %d\n", p[size - 1], old_chksum);
|
||||||
|
throwBadLoader();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// store new header_checksum
|
||||||
p[size - 1] = get_packheader_checksum(p, size - 1);
|
p[size - 1] = get_packheader_checksum(p, size - 1);
|
||||||
#endif /* UNUPX */
|
#endif /* UNUPX */
|
||||||
}
|
}
|
||||||
@@ -167,7 +198,7 @@ void PackHeader::putPackHeader(upx_bytep p)
|
|||||||
|
|
||||||
bool PackHeader::fillPackHeader(const upx_bytep buf, int blen)
|
bool PackHeader::fillPackHeader(const upx_bytep buf, int blen)
|
||||||
{
|
{
|
||||||
int boff = find_le32(buf, blen, magic);
|
int boff = find_le32(buf, blen, UPX_MAGIC_LE32);
|
||||||
if (boff < 0)
|
if (boff < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -216,6 +247,7 @@ bool PackHeader::fillPackHeader(const upx_bytep buf, int blen)
|
|||||||
u_file_size = get_le32(p+24);
|
u_file_size = get_le32(p+24);
|
||||||
off_filter = 28;
|
off_filter = 28;
|
||||||
filter_cto = p[29];
|
filter_cto = p[29];
|
||||||
|
n_mru = p[30] ? 1+ p[30] : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -227,6 +259,7 @@ bool PackHeader::fillPackHeader(const upx_bytep buf, int blen)
|
|||||||
u_file_size = get_be32(p+24);
|
u_file_size = get_be32(p+24);
|
||||||
off_filter = 28;
|
off_filter = 28;
|
||||||
filter_cto = p[29];
|
filter_cto = p[29];
|
||||||
|
n_mru = p[30] ? 1+ p[30] : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version >= 10)
|
if (version >= 10)
|
||||||
|
|||||||
+37
-9
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -31,11 +31,13 @@
|
|||||||
#include "packmast.h"
|
#include "packmast.h"
|
||||||
#include "packer.h"
|
#include "packer.h"
|
||||||
#include "lefile.h"
|
#include "lefile.h"
|
||||||
|
#include "p_elf.h"
|
||||||
|
|
||||||
#include "p_com.h"
|
#include "p_com.h"
|
||||||
#include "p_djgpp2.h"
|
#include "p_djgpp2.h"
|
||||||
#include "p_exe.h"
|
#include "p_exe.h"
|
||||||
#include "p_elf.h"
|
|
||||||
#include "p_unix.h"
|
#include "p_unix.h"
|
||||||
|
#include "p_lx_exc.h"
|
||||||
#include "p_lx_elf.h"
|
#include "p_lx_elf.h"
|
||||||
#include "p_lx_sep.h"
|
#include "p_lx_sep.h"
|
||||||
#include "p_lx_sh.h"
|
#include "p_lx_sh.h"
|
||||||
@@ -44,8 +46,10 @@
|
|||||||
#include "p_wcle.h"
|
#include "p_wcle.h"
|
||||||
#include "p_tmt.h"
|
#include "p_tmt.h"
|
||||||
#include "p_vxd.h"
|
#include "p_vxd.h"
|
||||||
|
#include "p_w16ne.h"
|
||||||
#include "p_w32pe.h"
|
#include "p_w32pe.h"
|
||||||
#include "p_vmlinz.h"
|
#include "p_vmlinz.h"
|
||||||
|
#include "p_ps1.h"
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
@@ -92,11 +96,12 @@ static Packer* try_pack(Packer *p, InputFile *f)
|
|||||||
f->seek(0,SEEK_SET);
|
f->seek(0,SEEK_SET);
|
||||||
if (p->canPack())
|
if (p->canPack())
|
||||||
{
|
{
|
||||||
|
if (opt->cmd == CMD_COMPRESS)
|
||||||
p->updatePackHeader();
|
p->updatePackHeader();
|
||||||
f->seek(0,SEEK_SET);
|
f->seek(0,SEEK_SET);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
} catch (IOException&) {
|
} catch (const IOException&) {
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
delete p;
|
delete p;
|
||||||
throw;
|
throw;
|
||||||
@@ -160,6 +165,8 @@ static Packer* try_packers(InputFile *f, try_function func)
|
|||||||
if ((p = func(new PackVxd(f),f)) != NULL)
|
if ((p = func(new PackVxd(f),f)) != NULL)
|
||||||
return p;
|
return p;
|
||||||
#endif
|
#endif
|
||||||
|
if ((p = func(new PackW16Ne(f),f)) != NULL)
|
||||||
|
return p;
|
||||||
if ((p = func(new PackW32Pe(f),f)) != NULL)
|
if ((p = func(new PackW32Pe(f),f)) != NULL)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -172,9 +179,23 @@ static Packer* try_packers(InputFile *f, try_function func)
|
|||||||
if ((p = func(new PackTos(f),f)) != NULL)
|
if ((p = func(new PackTos(f),f)) != NULL)
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
|
//
|
||||||
|
// linux kernel
|
||||||
|
//
|
||||||
|
if ((p = func(new PackVmlinuzI386(f),f)) != NULL)
|
||||||
|
return p;
|
||||||
|
if ((p = func(new PackBvmlinuzI386(f),f)) != NULL)
|
||||||
|
return p;
|
||||||
|
#if 0
|
||||||
|
if ((p = func(new PackElks8086(f),f)) != NULL)
|
||||||
|
return p;
|
||||||
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// linux
|
// linux
|
||||||
//
|
//
|
||||||
|
if (!opt->unix.force_execve)
|
||||||
|
{
|
||||||
#if 0
|
#if 0
|
||||||
if (opt->unix.script_name)
|
if (opt->unix.script_name)
|
||||||
{
|
{
|
||||||
@@ -186,13 +207,16 @@ static Packer* try_packers(InputFile *f, try_function func)
|
|||||||
return p;
|
return p;
|
||||||
if ((p = func(new PackLinuxI386sh(f),f)) != NULL)
|
if ((p = func(new PackLinuxI386sh(f),f)) != NULL)
|
||||||
return p;
|
return p;
|
||||||
if ((p = func(new PackBvmlinuzI386(f),f)) != NULL)
|
}
|
||||||
return p;
|
|
||||||
if ((p = func(new PackVmlinuzI386(f),f)) != NULL)
|
|
||||||
return p;
|
|
||||||
if ((p = func(new PackLinuxI386(f),f)) != NULL)
|
if ((p = func(new PackLinuxI386(f),f)) != NULL)
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
|
//
|
||||||
|
// psone
|
||||||
|
//
|
||||||
|
if ((p = func(new PackPs1(f),f)) != NULL)
|
||||||
|
return p;
|
||||||
|
|
||||||
//
|
//
|
||||||
// .sys and .com
|
// .sys and .com
|
||||||
//
|
//
|
||||||
@@ -224,7 +248,11 @@ static Packer *getUnpacker(InputFile *f)
|
|||||||
|
|
||||||
static void assertPacker(const Packer *p)
|
static void assertPacker(const Packer *p)
|
||||||
{
|
{
|
||||||
|
assert(p->getFormat() > 0);
|
||||||
|
assert(p->getFormat() <= 255);
|
||||||
assert(p->getVersion() >= 11);
|
assert(p->getVersion() >= 11);
|
||||||
|
assert(p->getVersion() < 255);
|
||||||
|
assert(p->getVersion() == 13);
|
||||||
assert(strlen(p->getName()) <= 13);
|
assert(strlen(p->getName()) <= 13);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2000 Laszlo Molnar
|
Copyright (C) 1996-2002 Laszlo Molnar
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||||
markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu
|
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user