Compare commits
261 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 | |||
| adcb357242 | |||
| 1e1a078808 | |||
| 7d652fa42b | |||
| a42e72094a | |||
| 97ff8042b4 |
@@ -1,5 +1,4 @@
|
||||
.cvsignore
|
||||
.mfxcvsup
|
||||
ChangeLog.cvs*
|
||||
build
|
||||
maint
|
||||
|
||||
@@ -8,9 +8,8 @@
|
||||
|
||||
|
||||
The Ultimate Packer for eXecutables
|
||||
Copyright (c) 1996-2000 Markus Oberhumer & Laszlo Molnar
|
||||
http://wildsau.idv.uni-linz.ac.at/mfx/upx.html
|
||||
http://upx.tsx.org
|
||||
Copyright (c) 1996-2002 Markus Oberhumer & Laszlo Molnar
|
||||
http://upx.sourceforge.net
|
||||
|
||||
|
||||
Limitations and other things which are not (yet) supported:
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
# Toplevel Makefile for UPX
|
||||
|
||||
all:
|
||||
$(MAKE) -C src/stub
|
||||
$(MAKE) -C src
|
||||
$(MAKE) -C doc
|
||||
SHELL = /bin/sh
|
||||
|
||||
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 $@
|
||||
$(MAKE) -C doc $@
|
||||
@@ -13,12 +15,16 @@ mostlyclean clean distclean maintainer-clean:
|
||||
dist: distclean
|
||||
false
|
||||
|
||||
zip:
|
||||
cd .. && rm -f upx-current.zip && zip -r upx-current.zip upx
|
||||
|
||||
cvs-admin-ko:
|
||||
cvs admin -ko .
|
||||
cvs update
|
||||
|
||||
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: dist cvs-admin-ko ChangeLog
|
||||
|
||||
@@ -2,14 +2,89 @@
|
||||
User visible changes for UPX
|
||||
==================================================================
|
||||
|
||||
Changes in 1.10 beta (20 Dec 2000):
|
||||
* UNSTABLE BETA VERSION - DO NOT USE EXCEPT FOR TESTING!!! REALLY.
|
||||
[ 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):
|
||||
* UNSTABLE BETA VERSION - DO NOT USE EXCEPT FOR TESTING
|
||||
* 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!
|
||||
* reduced overall memory requirements during packing
|
||||
* 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)
|
||||
* dos/exe: fixed an internal error when using `--no-reloc'
|
||||
* 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
|
||||
an illegal value
|
||||
* 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 speed
|
||||
|
||||
|
||||
@@ -8,9 +8,8 @@
|
||||
|
||||
|
||||
The Ultimate Packer for eXecutables
|
||||
Copyright (c) 1996-2000 Markus Oberhumer & Laszlo Molnar
|
||||
http://wildsau.idv.uni-linz.ac.at/mfx/upx.html
|
||||
http://upx.tsx.org
|
||||
Copyright (c) 1996-2002 Markus Oberhumer & Laszlo Molnar
|
||||
http://upx.sourceforge.net
|
||||
|
||||
|
||||
Here are some possible projects from which you can choose if you'd like to
|
||||
@@ -31,8 +30,19 @@ User interface:
|
||||
More formats:
|
||||
-------------
|
||||
|
||||
- add more file formats / platforms (there were volunteers for FreeBSD,
|
||||
BeOS, Windows CE, Amiga, C64, ...)
|
||||
- Amiga
|
||||
|
||||
- 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
|
||||
(like the AlgART HTML Packer "AHP")
|
||||
@@ -41,23 +51,20 @@ More 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
|
||||
|
||||
- djgpp2/coff: add support for DLX dynamic loading
|
||||
(see SEAL http://www.home.sk/public/seal/ )
|
||||
- dos/sys: add support for sys/exe combos
|
||||
|
||||
- linux/i386:
|
||||
- use the new assembly preprocessor stuff (ie. process the file
|
||||
headers internally)
|
||||
- UPX uncompressor daemon
|
||||
- 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
|
||||
|
||||
@@ -65,8 +72,6 @@ Existing formats:
|
||||
of problems (like importing a DLL or function fails)
|
||||
- win32/pe: finer control over resource compression, per section
|
||||
compression
|
||||
- win32/pe: compressing screensavers looses the description - probably
|
||||
should not compress a special resource type
|
||||
|
||||
|
||||
Compression ratio:
|
||||
|
||||
@@ -8,23 +8,22 @@
|
||||
|
||||
|
||||
The Ultimate Packer for eXecutables
|
||||
Copyright (c) 1996-2000 Markus Oberhumer & Laszlo Molnar
|
||||
http://wildsau.idv.uni-linz.ac.at/mfx/upx.html
|
||||
http://upx.tsx.org
|
||||
Copyright (c) 1996-2002 Markus Oberhumer & Laszlo Molnar
|
||||
http://upx.sourceforge.net
|
||||
|
||||
|
||||
|
||||
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 !
|
||||
There will be hidden bugs. Really.
|
||||
|
||||
The current stable release is 1.04, and the next stable release
|
||||
will be called version 1.20.
|
||||
The current stable release is 1.22, and the next stable release
|
||||
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
|
||||
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 to UPX 1.0x, the first production release after almost two years
|
||||
of beta testing.
|
||||
Welcome to UPX !
|
||||
|
||||
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
|
||||
allowing the distribution of all compressed executables, including
|
||||
commercial programs.
|
||||
@@ -54,8 +52,8 @@ and run exactly as before, with no runtime or memory penalty for most
|
||||
of the supported formats.
|
||||
|
||||
UPX supports a number of different executable formats, including
|
||||
Win95/98/ME/NT/2000 programs and DLLs, DOS programs, and Linux
|
||||
executables and kernels.
|
||||
Windows 95/98/ME/NT/2000/XP programs and DLLs, DOS programs,
|
||||
and Linux executables and kernels.
|
||||
|
||||
UPX is free software distributed under the term of the GNU General
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
@@ -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
|
||||
have compressed lots of files without any problems. Also, the
|
||||
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
|
||||
releases will be backward compatible with this version.
|
||||
@@ -114,8 +112,7 @@ THE FUTURE
|
||||
This only gives people a false feeling of security because
|
||||
by definition all protectors/compressors can be broken.
|
||||
And don't trust any advertisment of authors of other executable
|
||||
compressors about this topic - just do a websearch on something
|
||||
like "procdump"...
|
||||
compressors about this topic - just do a websearch on "unpackers"...
|
||||
|
||||
- Fix all remaining bugs - keep your reports coming ;-)
|
||||
|
||||
@@ -126,8 +123,8 @@ THE FUTURE
|
||||
COPYRIGHT
|
||||
=========
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2002 Laszlo Molnar
|
||||
|
||||
This program may be used freely, and you are welcome to
|
||||
redistribute it under certain conditions.
|
||||
@@ -146,7 +143,7 @@ Markus & Laszlo
|
||||
|
||||
|
||||
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
|
||||
===============================
|
||||
|
||||
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 !
|
||||
There will be hidden bugs. Really.
|
||||
|
||||
The current stable release is 1.04, and the next stable release
|
||||
will be called version 1.20.
|
||||
|
||||
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 current stable release is 1.24, and the next stable release
|
||||
will be called version 2.00.
|
||||
|
||||
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
|
||||
|
||||
|
||||
+19
-19
@@ -60,17 +60,16 @@ Prerequisites
|
||||
-------------
|
||||
|
||||
- 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
|
||||
--------------------------------------------
|
||||
|
||||
- A modern C++ compiler like gcc 2.95.2 or Visual C++ 6
|
||||
(egcs 1.1.x may work, half-baked implementations like Borland C++ 5.5 won't)
|
||||
- A modern C++ compiler like gcc 2.95.3 or Visual C++ 6
|
||||
|
||||
- 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
|
||||
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 UCLDIR=c:\src\ucl-0.92 (DOS / Windows)
|
||||
export UCLDIR=$HOME/local/src/ucl-0.92 (Unix)
|
||||
set UCLDIR=c:\src\ucl-1.01 (DOS / Windows)
|
||||
export UCLDIR=$HOME/local/src/ucl-1.01 (Unix)
|
||||
|
||||
then type
|
||||
|
||||
make target=linux # on linux
|
||||
make target=djgpp2 # for djgpp2
|
||||
make target=mingw32 # for mingw32
|
||||
make target=no-cygwin # for mingw32 as included in cygwin
|
||||
make target=msc # for Visual C++ 6.0
|
||||
make target=linux # on linux
|
||||
make target=djgpp2 # for djgpp2
|
||||
make target=mingw32 # for mingw32
|
||||
make target=cygwin # cygwin 1.3.x
|
||||
make target=no-cygwin # for mingw32 as included in cygwin
|
||||
make target=vc6 # for Visual C++ 6.0
|
||||
|
||||
|
||||
If you want to modify the stub sources you'll also need
|
||||
-------------------------------------------------------
|
||||
|
||||
- Nasm - the Netwide Assembler
|
||||
http://www.cryogen.com/Nasm
|
||||
|
||||
- Perl 5.004 or better
|
||||
ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/perl*b.zip
|
||||
- Nasm 0.98.34 - the Netwide Assembler
|
||||
http://upx.sourceforge.net/download/tools/
|
||||
http://nasm.sourceforge.net/
|
||||
|
||||
- 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
|
||||
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
|
||||
|
||||
@@ -8,9 +8,8 @@
|
||||
|
||||
|
||||
The Ultimate Packer for eXecutables
|
||||
Copyright (c) 1996-2000 Markus Oberhumer & Laszlo Molnar
|
||||
http://wildsau.idv.uni-linz.ac.at/mfx/upx.html
|
||||
http://upx.tsx.org
|
||||
Copyright (c) 1996-2002 Markus Oberhumer & Laszlo Molnar
|
||||
http://upx.sourceforge.net
|
||||
|
||||
|
||||
.___.. .
|
||||
|
||||
@@ -1,186 +1,111 @@
|
||||
- The UCL license is GPL, this will cause problems for the antivirus
|
||||
programs which can't use the uncompressor because of this. Or am I wrong?
|
||||
UPX TODO list. Last updated 2002-11-11.
|
||||
|
||||
- Rearrange this TODO list, sort by categories, add a priority (1-5)
|
||||
- check all <const_cast> to make sure they are not invalid
|
||||
|
||||
- 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
|
||||
or resource names a,b,c
|
||||
|
||||
3 - medium - ml) rebuild exports
|
||||
|
||||
3 - difficult) don't compress the BSS section and other holes.
|
||||
|
||||
4 - medium - ml) fix when objectalign < 0x1000
|
||||
|
||||
4 - easy - ml) put the original offset of moved resources somewhere into
|
||||
the res.dir. (if it's safe to do)
|
||||
|
||||
4 - ??? - ml) fix FIXMEs
|
||||
|
||||
5 - medium - ml) try to put the preprocessed imports & relocs back to their
|
||||
original section if possible this could save some virtual memory
|
||||
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
|
||||
original section if possible. this could save some virtual memory
|
||||
address space.
|
||||
|
||||
|
||||
+3
-3
@@ -3,14 +3,14 @@ SHELL = /bin/sh
|
||||
top_srcdir = ..
|
||||
|
||||
PACKAGE = upx
|
||||
VERSION_DATE = 20 Dec 2000
|
||||
VERSION := $(shell sed -n 's/^.*UPX_VERSION_STRING.*"\(.*\)".*/\1/p' $(top_srcdir)/src/version.h)
|
||||
VERSION_DATE = 11 Nov 2002
|
||||
VERSION := $(shell sed -n 's/^.*UPX_VERSION_STRING .*"\(.*\)".*/\1/p' $(top_srcdir)/src/version.h)
|
||||
|
||||
TRIMSPACE = cat
|
||||
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
|
||||
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
|
||||
that do the runtime decompression when a compressed program is started.
|
||||
|
||||
|
||||
+172
-63
@@ -12,11 +12,9 @@ B<upx> S<[ I<command> ]> S<[ I<options> ]> I<filename>...
|
||||
|
||||
=head1 ABSTRACT
|
||||
|
||||
The Ultimate Packer for eXecutables
|
||||
Copyright (c) 1996, 1997, 1998, 1999, 2000
|
||||
Markus F.X.J. Oberhumer, Laszlo Molnar & John F. Reiser
|
||||
http://wildsau.idv.uni-linz.ac.at/mfx/upx.html
|
||||
http://upx.tsx.org
|
||||
The Ultimate Packer for eXecutables
|
||||
Copyright (c) 1996-2002 Markus Oberhumer & Laszlo Molnar
|
||||
http://upx.sourceforge.net
|
||||
|
||||
|
||||
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
|
||||
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
|
||||
appreciate if you credit UPX and ourselves in the documentation,
|
||||
possibly including a reference to the UPX home page. Thanks.
|
||||
appreciate if you credit B<UPX> and ourselves in the documentation,
|
||||
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 ;-) ]
|
||||
|
||||
|
||||
|
||||
=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
|
||||
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
|
||||
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/elf386
|
||||
* linux/sh386
|
||||
* ps1/exe
|
||||
* rtm32/pe
|
||||
* tmt/adam
|
||||
* 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
|
||||
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.
|
||||
|
||||
|
||||
@@ -105,7 +104,7 @@ specified on the command line.
|
||||
|
||||
=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.
|
||||
|
||||
=head2 Test
|
||||
@@ -135,9 +134,7 @@ B<-q -q -q> (or B<-qqq>): produce no output at all
|
||||
|
||||
B<--help>: prints the help
|
||||
|
||||
B<--version>: print the version of UPX
|
||||
|
||||
B<--stdout>: writes all output to stdout
|
||||
B<--version>: print the version of B<UPX>
|
||||
|
||||
[ ...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 compress a multi-megabyte program. You have been warned.
|
||||
|
||||
Tips for even better compression:
|
||||
Tips for achieving the best compression ratio:
|
||||
|
||||
=over 4
|
||||
|
||||
=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.
|
||||
|
||||
=item *
|
||||
@@ -216,23 +224,19 @@ all executable formats.
|
||||
=head1 ENVIRONMENT
|
||||
|
||||
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.
|
||||
For example:
|
||||
|
||||
for DOS/Windows: set UPX=-9 --compress-icons#1
|
||||
for sh/ksh/zsh: UPX="-9 --compress-icons=1"; export UPX
|
||||
for csh/tcsh: setenv UPX "-9 --compress-icons=1"
|
||||
for DOS/Windows: set UPX=-9 --compress-icons#0
|
||||
for sh/ksh/zsh: UPX="-9 --compress-icons=0"; export UPX
|
||||
for csh/tcsh: setenv UPX "-9 --compress-icons=0"
|
||||
|
||||
Under DOS/Windows you must use '#' instead of '=' when setting the
|
||||
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 -
|
||||
UPX will tell you.
|
||||
B<UPX> will tell you.
|
||||
|
||||
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
|
||||
|
||||
This is the executable format used by the Atari ST/TT, a 68000 based
|
||||
personal computer which was popular in the late '80s. Support
|
||||
This is the executable format used by the Atari ST/TT, a Motorola 68000
|
||||
based personal computer which was popular in the late '80s. Support
|
||||
of this format is only because of nostalgic feelings of one of
|
||||
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:
|
||||
|
||||
(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
|
||||
|
||||
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).
|
||||
|
||||
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.
|
||||
|
||||
--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
|
||||
|
||||
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).
|
||||
|
||||
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.
|
||||
|
||||
--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
|
||||
@@ -311,33 +333,51 @@ Extra options available for this executable format:
|
||||
|
||||
--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
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
Packed programs will be byte-identical to the original after uncompression.
|
||||
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:
|
||||
|
||||
--coff Produce COFF output instead of EXE. By default
|
||||
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]
|
||||
@@ -520,7 +560,7 @@ Extra options available for this executable format:
|
||||
Please read the general Linux description first.
|
||||
|
||||
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
|
||||
script as an argument with a leading ``-c''.
|
||||
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.
|
||||
|
||||
The generic linux/386 format deompresses to /tmp
|
||||
and needs /proc filesystem support.
|
||||
The generic linux/386 format decompresses to /tmp and needs
|
||||
/proc filesystem support. It starts the decompressed program
|
||||
via the execve() syscall.
|
||||
|
||||
Linux/386 is only selected if the specialized linux/elf386
|
||||
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:
|
||||
|
||||
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 -
|
||||
because of the good memory management of the Linux kernel - this
|
||||
often does not introduce a noticable delay, and in fact there
|
||||
@@ -625,7 +666,44 @@ Specific drawbacks:
|
||||
|
||||
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:
|
||||
|
||||
(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
|
||||
|
||||
The vmlinuz/386 and bvmlinuz/386 formats take a gzip-compressed
|
||||
bootable kernel image ("vmlinuz", "zImage", "bzImage"), gzip-decompress
|
||||
it and re-compress it with the UPX compression method.
|
||||
bootable Linux kernel image ("vmlinuz", "zImage", "bzImage"),
|
||||
gzip-decompress it and re-compress it with the B<UPX> compression method.
|
||||
|
||||
vmlinuz/386 is completely unrelated to the other Linux executable
|
||||
formats, and it does not share any of their drawbacks.
|
||||
@@ -672,7 +758,8 @@ Benefits:
|
||||
641073 bzImage [original]
|
||||
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:
|
||||
|
||||
@@ -680,22 +767,26 @@ Drawbacks:
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
The WDOS/X extender is partly supported (for details
|
||||
see the file bugs BUGS).
|
||||
|
||||
Yes, you can use your compressed executables with DOS4GW.
|
||||
|
||||
The LX format is not yet supported.
|
||||
|
||||
DLLs are not supported.
|
||||
DLLs and the LX format are not supported.
|
||||
|
||||
Extra options available for this executable format:
|
||||
|
||||
@@ -706,10 +797,10 @@ Extra options available for this executable format:
|
||||
|
||||
=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.
|
||||
|
||||
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
|
||||
several instances of huge compressed programs you're wasting memory
|
||||
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.
|
||||
|
||||
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:
|
||||
|
||||
--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
|
||||
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
|
||||
@@ -775,22 +880,26 @@ Please report all bugs immediately to the authors.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Markus F.X.J. Oberhumer <markus.oberhumer@jk.uni-linz.ac.at>
|
||||
http://wildsau.idv.uni-linz.ac.at/mfx/
|
||||
Markus F.X.J. Oberhumer <markus@oberhumer.com>
|
||||
http://www.oberhumer.com
|
||||
|
||||
Laszlo Molnar <ml1050@cdata.tvnet.hu>
|
||||
Laszlo Molnar <ml1050@users.sourceforge.net>
|
||||
|
||||
John F. Reiser <jreiser@BitWagon.com>
|
||||
|
||||
Jens Medoch <jssg@users.sourceforge.net>
|
||||
|
||||
|
||||
|
||||
=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
|
||||
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,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
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
|
||||
with this program; see the file LICENSE. If not, visit the UPX home page.
|
||||
|
||||
+170
-52
@@ -8,8 +8,8 @@ exec perl -w -x $0 ${1+"$@"} # -*- mode: perl; perl-indent-level: 2; -*-
|
||||
### ###
|
||||
##############################################################
|
||||
|
||||
## $Revision: 2.29 $
|
||||
## $Date: 2000/09/06 16:57:18 $
|
||||
## $Revision: 2.38 $
|
||||
## $Date: 2001/02/12 19:54:35 $
|
||||
## $Author: kfogel $
|
||||
##
|
||||
## (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";
|
||||
|
||||
# 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/;
|
||||
|
||||
## Vars set by options:
|
||||
@@ -98,6 +98,10 @@ my $Distributed = 0;
|
||||
# What file should we generate (defaults to "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?
|
||||
my $User_Map_File = "";
|
||||
|
||||
@@ -196,6 +200,33 @@ my $logmsg_separator = "----------------------------";
|
||||
|
||||
### 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.
|
||||
sub derive_change_log ()
|
||||
{
|
||||
@@ -210,6 +241,12 @@ sub derive_change_log ()
|
||||
my $msg_txt;
|
||||
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
|
||||
my %usermap;
|
||||
|
||||
@@ -605,6 +642,7 @@ sub derive_change_log ()
|
||||
undef $file_full_path;
|
||||
undef %branch_names;
|
||||
undef %branch_numbers;
|
||||
undef %symbolic_names;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -640,12 +678,12 @@ sub derive_change_log ()
|
||||
my $msghash = $timehash->{$time};
|
||||
while (my ($msg,$qunklist) = each %$msghash)
|
||||
{
|
||||
my $stamptime = $stamptime{$msg};
|
||||
my $stamptime = $stamptime{$msg};
|
||||
if ((defined $stamptime)
|
||||
and (($time - $stamptime) < $Max_Checkin_Duration)
|
||||
and (defined $changelog{$stamptime}{$author}{$msg}))
|
||||
{
|
||||
push(@{$changelog{$stamptime}{$author}{$msg}}, @$qunklist);
|
||||
push(@{$changelog{$stamptime}{$author}{$msg}}, @$qunklist);
|
||||
}
|
||||
else {
|
||||
$changelog{$time}{$author}{$msg} = $qunklist;
|
||||
@@ -736,7 +774,7 @@ sub derive_change_log ()
|
||||
elsif ($No_Wrap)
|
||||
{
|
||||
$msg = &preprocess_msg_text ($msg);
|
||||
$files = wrap ("\t", " ", "$files");
|
||||
$files = wrap ("\t", " ", "$files");
|
||||
$msg =~ s/\n(.*)/\n\t$1/g;
|
||||
unless ($After_Header eq " ") {
|
||||
$msg =~ s/^(.*)/\t$1/g;
|
||||
@@ -804,6 +842,41 @@ sub derive_change_log ()
|
||||
|
||||
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) {
|
||||
rename ($logfile_here, $logfile_bak);
|
||||
}
|
||||
@@ -1017,7 +1090,7 @@ sub pretty_file_list ()
|
||||
# Collect the revision numbers' last components, but don't
|
||||
# print them -- they'll get printed with the branch name
|
||||
# later.
|
||||
$$qunkref{'revision'} =~ /.+\.([\d])+$/;
|
||||
$$qunkref{'revision'} =~ /.+\.([\d]+)$/;
|
||||
push (@brevisions, $1);
|
||||
|
||||
# todo: we're still collecting branch roots, but we're not
|
||||
@@ -1185,17 +1258,18 @@ sub last_line_len ()
|
||||
# log entries.
|
||||
sub wrap_log_entry ()
|
||||
{
|
||||
my $text = shift; # The text to wrap.
|
||||
my $left_pad_str = shift; # String to pad with on the left.
|
||||
my $text = shift; # The text to wrap.
|
||||
my $left_pad_str = shift; # String to pad with on the left.
|
||||
|
||||
# These do NOT take left_pad_str into account:
|
||||
my $length_remaining = shift; # Amount left on current line.
|
||||
my $max_line_length = shift; # Amount left for a blank line.
|
||||
my $length_remaining = shift; # Amount left on current line.
|
||||
my $max_line_length = shift; # Amount left for a blank line.
|
||||
|
||||
my $wrapped_text = ""; # The accumulating wrapped entry.
|
||||
my $indentation = ""; # Inherited indentation from prev line.
|
||||
my $wrapped_text = ""; # The accumulating wrapped entry.
|
||||
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);
|
||||
while (@lines) # Don't use `foreach' here, it won't work.
|
||||
@@ -1203,29 +1277,45 @@ sub wrap_log_entry ()
|
||||
my $this_line = shift (@lines);
|
||||
chomp $this_line;
|
||||
|
||||
# First, if it matches any of the line-start regexps, then print a
|
||||
# newline now...
|
||||
if (($this_line =~ /^(\s*)\*\s+[a-zA-Z0-9]/)
|
||||
|| ($this_line =~ /^(\s*)\* [a-zA-Z0-9_\.\/\+-]+/)
|
||||
|| ($this_line =~ /^(\s*)\([a-zA-Z0-9_\.\/\+-]+(\)|,\s*)/)
|
||||
|| ($this_line =~ /^(\s*)- +/)
|
||||
|| ($this_line =~ /^(\s*)[^\s]+:\s*$/)
|
||||
|| ($this_line =~ /^(\s*)\*\) +/)
|
||||
|| ($this_line =~ /^(\s*)[a-zA-Z0-9](\)|\.|\:) +/))
|
||||
if ($this_line =~ /^(\s+)/) {
|
||||
$user_indent = $1;
|
||||
}
|
||||
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_\.\/\+-]+(\)|,\s*)/)
|
||||
|| ($this_line =~ /^(\s+)(\S+)/)
|
||||
|| ($this_line =~ /^(\s*)- +/)
|
||||
|| ($this_line =~ /^()\s*$/)
|
||||
|| ($this_line =~ /^(\s*)\*\) +/)
|
||||
|| ($this_line =~ /^(\s*)[a-zA-Z0-9](\)|\.|\:) +/))
|
||||
{
|
||||
# Make a line break immediately, unless header separator is set
|
||||
# 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
|
||||
# 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;
|
||||
$length_remaining = $max_line_length - (length ($indentation));
|
||||
$length_remaining = $max_line_length - (length ($user_indent));
|
||||
}
|
||||
|
||||
# Now that any indentation has been preserved, strip off leading
|
||||
# Now that any user_indent has been preserved, strip off leading
|
||||
# whitespace, so up-folding has no ugly side-effects.
|
||||
$this_line =~ s/^\s*//;
|
||||
|
||||
@@ -1233,13 +1323,11 @@ sub wrap_log_entry ()
|
||||
my $this_len = length ($this_line);
|
||||
if ($this_len == 0)
|
||||
{
|
||||
# Blank lines should be preserved, and should cancel any
|
||||
# indentation level.
|
||||
$this_line = "\n${left_pad_str}";
|
||||
$indentation = "";
|
||||
# Blank lines should cancel any user_indent level.
|
||||
$user_indent = "";
|
||||
$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
|
||||
# a new line.
|
||||
@@ -1260,13 +1348,34 @@ sub wrap_log_entry ()
|
||||
$this_line .= "\n${left_pad_str}";
|
||||
|
||||
# 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 = $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);
|
||||
|
||||
# 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;
|
||||
}
|
||||
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 ($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
|
||||
# breaking it nicely, so just insert it verbatim, with
|
||||
@@ -1288,9 +1400,9 @@ sub wrap_log_entry ()
|
||||
}
|
||||
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);
|
||||
$length_remaining = $max_line_length - (length ($indentation));
|
||||
$length_remaining = $max_line_length - (length ($user_indent));
|
||||
$this_line = "\n${left_pad_str}";
|
||||
}
|
||||
}
|
||||
@@ -1315,7 +1427,7 @@ sub wrap_log_entry ()
|
||||
# Unconditionally indicate that loop has run at least once.
|
||||
$first_time = 0;
|
||||
|
||||
$wrapped_text .= "${this_line}";
|
||||
$wrapped_text .= "${user_indent}${this_line}";
|
||||
}
|
||||
|
||||
# One last bit of padding.
|
||||
@@ -1413,6 +1525,9 @@ sub parse_options ()
|
||||
my $narg = shift (@ARGV) || die "$arg needs argument.\n";
|
||||
$output_file = $narg;
|
||||
}
|
||||
elsif ($arg =~ /^--accum$/) {
|
||||
$Cumulative = 1;
|
||||
}
|
||||
elsif ($arg =~ /^--fsf$/) {
|
||||
$FSF_Style = 1;
|
||||
}
|
||||
@@ -1507,6 +1622,11 @@ sub parse_options ()
|
||||
$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
|
||||
# just leave now:
|
||||
if ($exit_with_admonishment) {
|
||||
@@ -1524,10 +1644,7 @@ sub parse_options ()
|
||||
|
||||
## Else no problems, so proceed.
|
||||
|
||||
if ($Output_To_Stdout) {
|
||||
undef $Log_File_Name; # not actually necessary
|
||||
}
|
||||
elsif ($output_file) {
|
||||
if ($output_file) {
|
||||
$Log_File_Name = $output_file;
|
||||
}
|
||||
}
|
||||
@@ -1627,6 +1744,7 @@ Options/Arguments:
|
||||
-S, --separate-header Blank line between each header and log message
|
||||
--no-wrap Don't auto-wrap log message (recommend -S also)
|
||||
--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
|
||||
--header FILE Get ChangeLog header from FILE ("-" means stdin)
|
||||
--xml Output XML instead of ChangeLog format
|
||||
@@ -1636,7 +1754,7 @@ Options/Arguments:
|
||||
-l OPTS, --log-opts OPTS Invoke like this "cvs ... log OPTS"
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
must work). Run "cvs2cl.pl --help" to see more advanced options.
|
||||
|
||||
See http://www.red-bean.com/~kfogel/cvs2cl.shtml for updates, and
|
||||
for instructions on getting anonymous CVS access to this script.
|
||||
See http://www.red-bean.com/cvs2cl for updates, and for instructions
|
||||
on getting anonymous CVS access to this script.
|
||||
|
||||
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
|
||||
|
||||
@@ -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'
|
||||
must work). Run "cvs2cl.pl --help" to see more advanced options.
|
||||
|
||||
See http://www.red-bean.com/~kfogel/cvs2cl.shtml for updates, and
|
||||
for instructions on getting anonymous CVS access to this script.
|
||||
See http://www.red-bean.com/cvs2cl for updates, and for instructions
|
||||
on getting anonymous CVS access to this script.
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
GNUmakefile
|
||||
*.0??
|
||||
*.dat
|
||||
*.idb
|
||||
*.img
|
||||
*.map
|
||||
*.raw
|
||||
*.rel
|
||||
*.pdb
|
||||
*.upx
|
||||
.gdbinit
|
||||
.Attic
|
||||
.deps
|
||||
compress_nrv.*
|
||||
upx
|
||||
upx_nrv
|
||||
upx_nrv.*
|
||||
|
||||
+361
-218
@@ -1,12 +1,19 @@
|
||||
# UPX Makefile (GNU make) - works with djgpp2/win32/unix
|
||||
#
|
||||
# UPX Makefile (GNU make) - works with unix/win32/djgpp2
|
||||
#
|
||||
# usage:
|
||||
# `make target=linux' # linux
|
||||
# `make target=djggp2' # djggp2 2.03
|
||||
# `make target=cygwin' # cygwin 1.1.x
|
||||
# `make target=mingw32' # mingw32
|
||||
# `make target=no-cygwin' # mingw32 as included in cygwin 1.1.x
|
||||
# `make target=vc6' # Visual C++ 6.0
|
||||
# `make target=linux' # linux
|
||||
# `make target=djggp2' # dos32 - djggp2 2.03
|
||||
# `make target=cygwin' # win32 - cygwin 1.3.x
|
||||
# `make target=mingw32' # win32 - mingw32
|
||||
# `make target=no-cygwin' # win32 - mingw32 as included in cygwin 1.3.x
|
||||
# `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)),)
|
||||
# change this to reflect where the UCL library is
|
||||
UCLDIR = $(HOME)/local/src/ucl-0.92
|
||||
UCLDIR = $(HOME)/local/src/ucl-1.01
|
||||
endif
|
||||
|
||||
##target =
|
||||
|
||||
DEBUG = 0
|
||||
|
||||
|
||||
@@ -28,23 +37,28 @@ SHELL = /bin/sh
|
||||
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .a .c .cpp .exe .lib .o .obj
|
||||
.SUFFIXES: .a .c .cpp .exe .lib .o .obj .rc .res .ttp
|
||||
|
||||
|
||||
srcdir = .
|
||||
top_srcdir = ..
|
||||
|
||||
VPATH = $(srcdir)
|
||||
|
||||
|
||||
# auto-detect the target unless given on the commandline
|
||||
target = djgpp2
|
||||
ifeq ($(strip $(target)),)
|
||||
##target = djgpp2
|
||||
ifneq ($(strip $(wildcard /usr/include/linux)),)
|
||||
target = linux
|
||||
endif
|
||||
ifneq ($(strip $(wildcard /platform/sun4?/kernel/unix)),)
|
||||
target = sparc
|
||||
##ifneq ($(strip $(wildcard /platform/sun4?/kernel/unix)),)
|
||||
##target = sparc
|
||||
##endif
|
||||
endif
|
||||
ifeq ($(target),msc)
|
||||
override target = vc6
|
||||
|
||||
ifeq ($(strip $(target)),)
|
||||
include please_specify_a_target
|
||||
endif
|
||||
|
||||
|
||||
@@ -59,15 +73,16 @@ override T = $(basename $@)
|
||||
# these use exceptions & RTTI
|
||||
OBJECTS1 = \
|
||||
compress$o except$o file$o lefile$o \
|
||||
filter$o mem$o msg$o stdcxx$o work$o ui$o \
|
||||
packer$o packhead$o packmast$o \
|
||||
p_com$o p_djgpp2$o p_exe$o p_lx_elf$o p_lx_sep$o p_lx_sh$o \
|
||||
p_sys$o p_tmt$o p_tos$o \
|
||||
p_unix$o p_vmlinz$o p_w32pe$o p_wcle$o
|
||||
filter$o linker$o mem$o msg$o stdcxx$o work$o ui$o \
|
||||
packer$o packerf$o packhead$o packmast$o \
|
||||
p_com$o p_djgpp2$o p_elks$o p_exe$o \
|
||||
p_lx_elf$o p_lx_exc$o p_lx_sep$o p_lx_sh$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
|
||||
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 \
|
||||
s_object$o s_djgpp2$o s_vcsa$o s_win32$o
|
||||
|
||||
@@ -75,43 +90,58 @@ OBJECTS2 = \
|
||||
OBJECTS3 =
|
||||
|
||||
OBJECTS = $(OBJECTS1) $(OBJECTS2) $(OBJECTS3)
|
||||
LIBS =
|
||||
RESOURCES =
|
||||
|
||||
|
||||
# /***********************************************************************
|
||||
# // compiler settings
|
||||
# ************************************************************************/
|
||||
|
||||
# default to a gcc unix-type compiler
|
||||
CC = gcc
|
||||
CXX = $(CC)
|
||||
DEFS =
|
||||
INCLUDES = -I$(srcdir)
|
||||
CFLAGS_OUTPUT = -o $@
|
||||
CXXFLAGS_OUTPUT = $(CFLAGS_OUTPUT)
|
||||
|
||||
LINK_EXE = $(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $@ $^ $(LDLIBS)
|
||||
STUBEDIT_EXE =
|
||||
###
|
||||
### default compiler (gcc under unix)
|
||||
###
|
||||
|
||||
o = .o
|
||||
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
|
||||
###
|
||||
|
||||
##CFLAGS_O = -Os
|
||||
CFLAGS_O = -O2
|
||||
##CFLAGS_WERROR = -Werror
|
||||
CFLAGS_WERROR =
|
||||
CFLAGS_W = $(CFLAGS_WERROR)
|
||||
CFLAGS_W += -Wall -W -Wcast-align -Wcast-qual -Wmissing-declarations -Wmissing-prototypes -Wshadow -Wwrite-strings
|
||||
##CFLAGS_M = -fno-builtin
|
||||
## CFLAGS_M += -malign-functions=0 -malign-jumps=0 -malign-loops=0
|
||||
CFLAGS_W += -Wall -W -Wcast-align -Wcast-qual -Wmissing-prototypes -Wpointer-arith -Wshadow -Wwrite-strings
|
||||
CFLAGS_M =
|
||||
##CFLAGS_M += -fno-builtin
|
||||
##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
|
||||
CXXFLAGS1 = $(CXXFLAGS)
|
||||
##CXXFLAGS1 += -fasynchronous-exceptions
|
||||
CXXFLAGS2 = $(CXXFLAGS) -fno-exceptions -fno-rtti
|
||||
|
||||
ifeq ($(DEBUG),1)
|
||||
@@ -125,9 +155,9 @@ else
|
||||
LDFLAGS = -s
|
||||
endif
|
||||
LDFLAGS += -Wl,-Map,$T.map
|
||||
LDLIBS =
|
||||
LDLIBS = -lz
|
||||
LIBDIRS =
|
||||
DOS_LDLIBS =
|
||||
DOS_LIBDIRS =
|
||||
|
||||
|
||||
@@ -139,16 +169,17 @@ UCLDIR:=$(strip $(subst \,/,$(UCLDIR)))
|
||||
NRVDIR:=$(strip $(subst \,/,$(NRVDIR)))
|
||||
u = ucl
|
||||
U = UCL
|
||||
upx_exe = upx$e
|
||||
upx_exe_tail =
|
||||
include $(srcdir)/Makefile.inc
|
||||
ifneq ($(strip $(wildcard $(NRVDIR)/include/nrv)),)
|
||||
u = nrv
|
||||
U = NRV
|
||||
upx_exe = upx_$u$e
|
||||
upx_exe_tail = _$(u)
|
||||
include $(srcdir)/Makefile.inc
|
||||
endif
|
||||
upx_exe = upx$(upx_exe_tail)$(e)
|
||||
|
||||
tmp := -Wl,--rpath,
|
||||
override tmp := -Wl,--rpath,
|
||||
LDRPATH := $(addprefix $(tmp),$(LIBDIRS))
|
||||
LIBDIRS += .
|
||||
LDLIBDIRS := $(addprefix -L,$(LIBDIRS))
|
||||
@@ -158,17 +189,19 @@ LDFLAGS += $(LDLIBDIRS)
|
||||
|
||||
|
||||
###
|
||||
### linux/i386
|
||||
### Linux
|
||||
###
|
||||
|
||||
ifeq ($(target),linux)
|
||||
e =
|
||||
###CC = /usr/local/packages/gcc-cvs/bin/g++
|
||||
override arch := $(shell uname -m | sed -e 's/^i[3456789]86$$/i386/')
|
||||
DEFS += '-DUPX_CONFIG_H="config_h/linux.h"'
|
||||
##CFLAGS_M += -mno-schedule-prologue
|
||||
CFLAGS_M += -march=i386 -mcpu=pentium
|
||||
CFLAGS_WERROR = -Werror
|
||||
DEFS += -D_FILE_OFFSET_BITS=64
|
||||
LDLIBS += -lmcheck
|
||||
ifeq ($(arch),i386)
|
||||
CC += -march=i386 -mcpu=i586
|
||||
##CFLAGS_M += -mno-schedule-prologue
|
||||
endif
|
||||
##CFLAGS_WERROR = -Werror
|
||||
|
||||
ifeq (1,2) # checkergcc
|
||||
CC = checkergcc
|
||||
@@ -176,25 +209,101 @@ ifeq (1,2) # checkergcc
|
||||
else
|
||||
ifeq ($(DEBUG),1)
|
||||
##CFLAGS += -O0 -gstabs+3
|
||||
CFLAGS += -O0 -gdwarf-2
|
||||
##CFLAGS += -O0 -gdwarf-2
|
||||
CFLAGS += -O0 -g
|
||||
else
|
||||
##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 # 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
|
||||
###
|
||||
|
||||
ifeq ($(target),djgpp2)
|
||||
CFLAGS_M += -mno-schedule-prologue
|
||||
CFLAGS_M += -march=i386 -mcpu=pentium
|
||||
e = .exe
|
||||
CC += -march=i386 -mcpu=i586
|
||||
##CFLAGS_M += -mno-schedule-prologue
|
||||
CFLAGS_WERROR = -Werror
|
||||
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
|
||||
|
||||
|
||||
@@ -203,113 +312,54 @@ endif # djgpp2
|
||||
###
|
||||
|
||||
ifeq ($(target),cygwin)
|
||||
CFLAGS_M += -mno-schedule-prologue
|
||||
CFLAGS_M += -march=i386 -mcpu=pentium
|
||||
CFLAGS_WERROR = -Werror
|
||||
e = .exe
|
||||
CC += -march=i386 -mcpu=i586
|
||||
CXXLD = g++
|
||||
##CFLAGS_M += -mno-schedule-prologue
|
||||
endif
|
||||
|
||||
ifeq ($(target),mingw32)
|
||||
CFLAGS_M += -mno-schedule-prologue
|
||||
CFLAGS_M += -march=i386 -mcpu=pentium
|
||||
e = .exe
|
||||
CC = gcc -mno-cygwin
|
||||
CC += -march=i386 -mcpu=i586
|
||||
CXXLD = g++ -mno-cygwin
|
||||
##CFLAGS_M += -mno-schedule-prologue
|
||||
endif
|
||||
|
||||
# mingw32 as included in cygwin
|
||||
ifeq ($(target),no-cygwin)
|
||||
e = .exe
|
||||
CC = gcc -mno-cygwin
|
||||
CFLAGS_M += -mno-schedule-prologue
|
||||
CFLAGS_M += -march=i386 -mcpu=pentium
|
||||
CFLAGS_WERROR = -Werror
|
||||
CC += -march=i386 -mcpu=i586
|
||||
CXXLD = g++ -mno-cygwin
|
||||
##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
|
||||
|
||||
|
||||
###
|
||||
### Microsoft 32-bit C/C++ Compiler 12.00 (aka Visual C++ 6)
|
||||
###
|
||||
|
||||
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)
|
||||
### Borland C++ 5.5.1
|
||||
###
|
||||
|
||||
ifeq ($(target),bcc)
|
||||
o = .obj
|
||||
a = .lib
|
||||
CC = bcc32
|
||||
CFLAGS = -w -w-par
|
||||
e = .exe
|
||||
CC = bcc32 -q
|
||||
CFLAGS = -w -w-aus -g1
|
||||
CXXFLAGS1 = $(CFLAGS)
|
||||
CXXFLAGS2 = $(CFLAGS)
|
||||
CXXFLAGS2 = $(CFLAGS) -x- -xd- -RT-
|
||||
CFLAGS_OUTPUT = -o$@
|
||||
LDFLAGS =
|
||||
LDLIBS = $(DOS_LDLIBS) zlib.lib
|
||||
LDLIBS = $(DOS_LDLIBS) zlib114.lib
|
||||
|
||||
ifneq ($(strip $(DOS_LIBDIRS)),)
|
||||
LIB := $(DOS_LIBDIRS);$(LIB)
|
||||
@@ -322,15 +372,136 @@ else
|
||||
CFLAGS += -O2 -d
|
||||
endif
|
||||
|
||||
LINK_EXE = $(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) -e$@ $^ $(LDLIBS)
|
||||
LINK_EXE = $(CXXLD) $(LDFLAGS) -e$@ $^ $(LDLIBS)
|
||||
|
||||
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)
|
||||
LDLIBS += -lefence
|
||||
endif
|
||||
@@ -347,10 +518,43 @@ ifeq (1,2)
|
||||
##LDFLAGS += -Wl,-defsym,_DYNAMIC=0
|
||||
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
|
||||
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)
|
||||
|
||||
.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)
|
||||
$(STUBEDIT_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)
|
||||
$(STUBIFY_EXE)
|
||||
$(CHMOD_EXE)
|
||||
|
||||
|
||||
mostlyclean:
|
||||
-rm -f *.d *.err *.i *.log *.map *~ gdb-trans*
|
||||
|
||||
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 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
|
||||
|
||||
@@ -411,72 +601,25 @@ ID:
|
||||
# // rules
|
||||
# ************************************************************************/
|
||||
|
||||
.c$o:
|
||||
%$o : %.c
|
||||
$(CC) $(DEFS) $(INCLUDES) $(CFLAGS) $(CFLAGS_OUTPUT) -c $<
|
||||
|
||||
.cpp$o:
|
||||
$(CXX) $(DEFS) $(INCLUDES) $(CXXFLAGS1) $(CXXFLAGS_OUTPUT) -c $<
|
||||
|
||||
$(OBJECTS1): %$o : %.cpp
|
||||
%$o : %.cpp
|
||||
$(CXX) $(DEFS) $(INCLUDES) $(CXXFLAGS1) $(CXXFLAGS_OUTPUT) -c $<
|
||||
|
||||
ifneq ($(strip $(OBJECTS2)),)
|
||||
$(OBJECTS2): %$o : %.cpp
|
||||
$(CXX) $(DEFS) $(INCLUDES) $(CXXFLAGS2) $(CXXFLAGS_OUTPUT) -c $<
|
||||
|
||||
ifneq ($(strip $(OBJECTS3)),)
|
||||
$(OBJECTS3): %$o : %.c
|
||||
$(CC) $(DEFS) $(INCLUDES) $(CFLAGS) $(CFLAGS_OUTPUT) -c $<
|
||||
endif
|
||||
|
||||
%.res : %.rc
|
||||
rc -l 0x409 -fo$@ $<
|
||||
|
||||
|
||||
# /***********************************************************************
|
||||
# // dependencies
|
||||
# ************************************************************************/
|
||||
|
||||
# FIXME: use automated dependencies
|
||||
|
||||
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
|
||||
include $(srcdir)/Makefile.dep
|
||||
|
||||
# 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)
|
||||
|
||||
ifneq ($(strip $(wildcard $(UDIR)/include)),) # { include
|
||||
DEFS += -DWITH_$(U)
|
||||
|
||||
ifneq ($(strip $(wildcard $(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)),)
|
||||
LIBDIRS += $(UDIR)/src/.libs
|
||||
endif
|
||||
@@ -35,3 +36,4 @@ LIBDIRS := $(LIBDIRS)
|
||||
LDLIBS := $(LDLIBS)
|
||||
DOS_LDLIBS := $(DOS_LDLIBS)
|
||||
|
||||
endif # } include
|
||||
|
||||
+150
-39
@@ -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.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<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;
|
||||
v = (unsigned) b[1] << 0;
|
||||
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[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;
|
||||
v = (unsigned) b[3] << 0;
|
||||
v |= (unsigned) b[2] << 8;
|
||||
@@ -62,9 +81,9 @@ inline unsigned get_be32(const void *bb, int off=0)
|
||||
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[2] = (unsigned char) (v >> 8);
|
||||
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__)
|
||||
v = * (const unsigned short *) b;
|
||||
return * (const unsigned short *) bb;
|
||||
#else
|
||||
const upx_bytep b = (const upx_bytep) bb;
|
||||
unsigned v;
|
||||
v = (unsigned) b[0] << 0;
|
||||
v |= (unsigned) b[1] << 8;
|
||||
return v;
|
||||
#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__)
|
||||
(* (unsigned short *) b) = (unsigned short) v;
|
||||
(* (unsigned short *) bb) = (unsigned short) (v & 0xffff);
|
||||
#else
|
||||
upx_bytep b = (upx_bytep) bb;
|
||||
b[0] = (unsigned char) (v >> 0);
|
||||
b[1] = (unsigned char) (v >> 8);
|
||||
#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;
|
||||
v = (unsigned) b[0] << 0;
|
||||
v |= (unsigned) b[1] << 8;
|
||||
@@ -107,36 +126,36 @@ inline unsigned get_le24(const void *bb, int off=0)
|
||||
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[1] = (unsigned char) (v >> 8);
|
||||
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__)
|
||||
v = * (const unsigned *) b;
|
||||
return * (const unsigned *) bb;
|
||||
#else
|
||||
const upx_bytep b = (const upx_bytep) bb;
|
||||
unsigned v;
|
||||
v = (unsigned) b[0] << 0;
|
||||
v |= (unsigned) b[1] << 8;
|
||||
v |= (unsigned) b[2] << 16;
|
||||
v |= (unsigned) b[3] << 24;
|
||||
#endif
|
||||
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__)
|
||||
(* (unsigned *) b) = v;
|
||||
(* (unsigned *) bb) = v;
|
||||
#else
|
||||
upx_bytep b = (upx_bytep) bb;
|
||||
b[0] = (unsigned char) (v >> 0);
|
||||
b[1] = (unsigned char) (v >> 8);
|
||||
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
|
||||
**************************************************************************/
|
||||
@@ -163,7 +230,8 @@ public:
|
||||
BE16& operator |= (unsigned v) { set_be16(d, get_be16(d) | v); return *this; }
|
||||
|
||||
operator const unsigned () const { return get_be16(d); }
|
||||
};
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
|
||||
class BE32
|
||||
@@ -180,7 +248,8 @@ public:
|
||||
BE32& operator |= (unsigned v) { set_be32(d, get_be32(d) | v); return *this; }
|
||||
|
||||
operator const unsigned () const { return get_be32(d); }
|
||||
};
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
|
||||
class LE16
|
||||
@@ -197,7 +266,8 @@ public:
|
||||
LE16& operator |= (unsigned v) { set_le16(d, get_le16(d) | v); return *this; }
|
||||
|
||||
operator const unsigned () const { return get_le16(d); }
|
||||
};
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
|
||||
class LE32
|
||||
@@ -214,7 +284,8 @@ public:
|
||||
LE32& operator |= (unsigned v) { set_le32(d, get_le32(d) | v); return *this; }
|
||||
|
||||
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
|
||||
**************************************************************************/
|
||||
|
||||
// for use with qsort()
|
||||
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 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 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 */
|
||||
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
/* c_file.cpp -- file console output
|
||||
/* c_file.cpp --
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
|
||||
+7
-7
@@ -1,9 +1,9 @@
|
||||
/* c_init.cpp -- console initialization
|
||||
/* c_init.cpp --
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
@@ -147,8 +147,8 @@ void con_fprintf(FILE *f, const char *format, ...)
|
||||
va_list args;
|
||||
char buf[80*25];
|
||||
|
||||
va_start(args,format);
|
||||
upx_vsnprintf(buf,sizeof(buf),format,args);
|
||||
va_start(args, format);
|
||||
upx_vsnprintf(buf, sizeof(buf), format,args);
|
||||
va_end(args);
|
||||
|
||||
if (con == me)
|
||||
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
/* c_none.cpp -- dummy console output
|
||||
/* c_none.cpp --
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
|
||||
+5
-5
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ static void print0(FILE *f, const char *ss)
|
||||
|
||||
// Note:
|
||||
// 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);
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
+17
-235
@@ -1,9 +1,9 @@
|
||||
/* compress.cpp -- interface to the compression library
|
||||
/* compress.cpp --
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,248 +21,30 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
#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)
|
||||
# include <nrv/nrv2b.h>
|
||||
# include <nrv/nrv2d.h>
|
||||
# if !defined(NRV_VERSION) || (NRV_VERSION < 0x007300L)
|
||||
# error
|
||||
# include "compress_nrv.ch"
|
||||
#elif defined(WITH_UCL)
|
||||
# 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
|
||||
# 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(...);
|
||||
# include "compress.ch"
|
||||
#else
|
||||
# error
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et:nowrap
|
||||
|
||||
+176
-183
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
@@ -36,11 +36,39 @@
|
||||
#if defined(UPX_CONFIG_H)
|
||||
# include UPX_CONFIG_H
|
||||
#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 "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(__386__) || defined(_M_IX86)
|
||||
# define __i386__ 1
|
||||
@@ -59,9 +87,15 @@
|
||||
#undef unix
|
||||
|
||||
|
||||
#if !defined(WITH_UCL)
|
||||
# error "you lose"
|
||||
#endif
|
||||
#if defined(WITH_UCL)
|
||||
# include <ucl/uclconf.h>
|
||||
# include <ucl/ucl.h>
|
||||
# if !defined(UCL_VERSION) || (UCL_VERSION < 0x010100L)
|
||||
# error "please upgrade your UCL installation"
|
||||
# endif
|
||||
# if !defined(UPX_UINT_MAX)
|
||||
# define UPX_UINT_MAX UCL_UINT_MAX
|
||||
# define upx_uint ucl_uint
|
||||
@@ -70,8 +104,8 @@
|
||||
# define upx_byte ucl_byte
|
||||
# define upx_bytep ucl_bytep
|
||||
# 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_adler32 ucl_adler32
|
||||
# define UPX_E_OK UCL_E_OK
|
||||
# define UPX_E_ERROR UCL_E_ERROR
|
||||
# define UPX_E_OUT_OF_MEMORY UCL_E_OUT_OF_MEMORY
|
||||
@@ -80,40 +114,15 @@
|
||||
#endif
|
||||
#if defined(WITH_NRV)
|
||||
# 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
|
||||
#if !defined(__UPX_CHECKER)
|
||||
# if defined(__UCL_CHECKER) || defined(__NRV_CHECKER)
|
||||
# define __UPX_CHECKER
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(UPX_UINT_MAX) || (UINT_MAX < 0xffffffffL)
|
||||
#if !defined(UINT_MAX) || (UINT_MAX < 0xffffffffL)
|
||||
# error "you lose"
|
||||
#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
|
||||
#if defined(WITH_DMALLOC)
|
||||
#if defined(WITH_VALGRIND)
|
||||
# include <valgrind.h>
|
||||
#elif defined(WITH_DMALLOC)
|
||||
# define DMALLOC_FUNC_CHECK
|
||||
# include <dmalloc.h>
|
||||
#elif defined(WITH_GC)
|
||||
@@ -189,9 +200,20 @@
|
||||
# define malloc GC_MALLOC
|
||||
# define realloc GC_REALLOC
|
||||
# define free GC_FREE
|
||||
#elif defined(WITH_MSS)
|
||||
# define MSS
|
||||
# include <mss.h>
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
|
||||
@@ -199,11 +221,18 @@
|
||||
// portab
|
||||
**************************************************************************/
|
||||
|
||||
#if defined(NO_BOOL)
|
||||
typedef int bool;
|
||||
enum { false, true };
|
||||
#if defined(__GNUC__) && !defined(__GNUC_VERSION_HEX__)
|
||||
# if !defined(__GNUC_MINOR__)
|
||||
# error
|
||||
# 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)
|
||||
# define PATH_MAX 512
|
||||
#elif (PATH_MAX < 512)
|
||||
@@ -220,6 +249,7 @@ enum { false, true };
|
||||
#endif
|
||||
typedef RETSIGTYPE (SIGTYPEENTRY *sig_type)(int);
|
||||
|
||||
|
||||
#undef MODE_T
|
||||
#if defined(HAVE_MODE_T)
|
||||
# define MODE_T mode_t
|
||||
@@ -227,6 +257,7 @@ typedef RETSIGTYPE (SIGTYPEENTRY *sig_type)(int);
|
||||
# define MODE_T int
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(HAVE_STRCASECMP)
|
||||
# if defined(HAVE_STRICMP)
|
||||
# define strcasecmp stricmp
|
||||
@@ -299,8 +330,43 @@ typedef RETSIGTYPE (SIGTYPEENTRY *sig_type)(int);
|
||||
#define index upx_index
|
||||
#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
|
||||
#endif
|
||||
|
||||
#if defined(__DMC__)
|
||||
# undef tell
|
||||
#endif
|
||||
|
||||
#if defined(__DJGPP__)
|
||||
# undef sopen
|
||||
# undef USE_SETMODE
|
||||
@@ -328,14 +398,17 @@ typedef RETSIGTYPE (SIGTYPEENTRY *sig_type)(int);
|
||||
// memory util
|
||||
**************************************************************************/
|
||||
|
||||
#undef FREE
|
||||
#define FREE(ptr) if (ptr) { free(ptr); ptr = NULL; }
|
||||
|
||||
#undef UNUSED
|
||||
#if defined(__BORLANDC__)
|
||||
#define UNUSED(parm) ((void)(parm))
|
||||
#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))
|
||||
#else
|
||||
#define UNUSED(parm) (parm = parm)
|
||||
# define UNUSED(parm) (parm = parm)
|
||||
#endif
|
||||
|
||||
#define HIGH(array) ((unsigned) (sizeof(array)/sizeof((array)[0])))
|
||||
@@ -349,56 +422,51 @@ typedef RETSIGTYPE (SIGTYPEENTRY *sig_type)(int);
|
||||
#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
|
||||
inline void *operator new(size_t l)
|
||||
{
|
||||
void *p = malloc(l);
|
||||
printf("new %6ld %p\n",(long)l,p);
|
||||
printf("new %6ld %p\n",(long)l,p);
|
||||
fflush(stdout);
|
||||
return p;
|
||||
}
|
||||
inline void *operator new[](size_t l)
|
||||
{
|
||||
void *p = malloc(l);
|
||||
printf("new %6ld %p\n",(long)l,p);
|
||||
printf("new[] %6ld %p\n",(long)l,p);
|
||||
fflush(stdout);
|
||||
return p;
|
||||
}
|
||||
inline void operator delete(void *p)
|
||||
{
|
||||
printf("delete %p\n",p);
|
||||
printf("delete %p\n",p);
|
||||
fflush(stdout);
|
||||
if (p) free(p);
|
||||
}
|
||||
inline void operator delete[](void *p)
|
||||
{
|
||||
printf("delete %p\n",p);
|
||||
printf("delete[] %p\n",p);
|
||||
fflush(stdout);
|
||||
if (p) free(p);
|
||||
}
|
||||
#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.
|
||||
// "var" is declared as a read-only reference to a pointer
|
||||
// and behaves exactly like an array "var[]".
|
||||
#if 0
|
||||
# define autoheap_array(type, var, size) \
|
||||
#define Array(type, var, size) \
|
||||
assert((int)(size) > 0); \
|
||||
vector<type> var ## _autoheap_vec((size)); \
|
||||
type * const & var = & var ## _autoheap_vec[0]
|
||||
#else
|
||||
# define autoheap_array(type, var, size) \
|
||||
assert((int)(size) > 0); \
|
||||
MemBuffer var ## _autoheap_buf((size)*(sizeof(type))); \
|
||||
type * const & var = (type *) (unsigned char *) var ## _autoheap_buf
|
||||
#endif
|
||||
MemBuffer var ## _membuf((size)*(sizeof(type))); \
|
||||
type * const & var = ((type *) var ## _membuf.getVoidPtr())
|
||||
|
||||
#define ByteArray(var, size) Array(unsigned char, var, size)
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
// constants
|
||||
**************************************************************************/
|
||||
|
||||
/* 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_8 6
|
||||
#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_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
|
||||
**************************************************************************/
|
||||
|
||||
#include "unupx.h"
|
||||
|
||||
#include "snprintf.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
||||
#include "stdcxx.h"
|
||||
#include "options.h"
|
||||
#include "except.h"
|
||||
#include "bele.h"
|
||||
#include "util.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
|
||||
extern const char *progname;
|
||||
@@ -549,7 +557,7 @@ void e_exit(int ec);
|
||||
void printSetNl(int need_nl);
|
||||
void printClearLine(FILE *f = NULL);
|
||||
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__)
|
||||
void printErr(const char *iname, const char *format, ...)
|
||||
__attribute__((format(printf,2,3)));
|
||||
@@ -590,38 +598,23 @@ void show_version(int);
|
||||
|
||||
|
||||
// compress.cpp
|
||||
#if defined(WITH_UCL)
|
||||
#define upx_compress_config_t ucl_compress_config_t
|
||||
#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
|
||||
unsigned upx_adler32(const void *buf, unsigned len, unsigned adler=1);
|
||||
unsigned upx_crc32(const void *buf, unsigned len, unsigned crc=0);
|
||||
|
||||
int upx_compress ( const upx_byte *src, upx_uint src_len,
|
||||
upx_byte *dst, upx_uint *dst_len,
|
||||
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,
|
||||
upx_uintp result);
|
||||
int upx_decompress ( const upx_byte *src, upx_uint src_len,
|
||||
upx_byte *dst, upx_uint *dst_len,
|
||||
upx_uintp result );
|
||||
int upx_decompress ( const upx_bytep src, upx_uint src_len,
|
||||
upx_bytep dst, upx_uintp dst_len,
|
||||
int method );
|
||||
int upx_test_overlap ( const upx_byte *buf, upx_uint src_off,
|
||||
upx_uint src_len, upx_uint *dst_len,
|
||||
int upx_test_overlap ( const upx_bytep buf, upx_uint src_off,
|
||||
upx_uint src_len, upx_uintp dst_len,
|
||||
int method );
|
||||
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
|
||||
+3
-14
@@ -29,12 +29,6 @@
|
||||
/* Define to `long' if <stddef.h> doesn't define. */
|
||||
/* #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. */
|
||||
/* #undef WITH_DMALLOC */
|
||||
|
||||
@@ -179,6 +173,9 @@
|
||||
/* Define if you have the <stddef.h> header file. */
|
||||
#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 HAVE_SYS_PARAM_H 1
|
||||
|
||||
@@ -225,14 +222,6 @@
|
||||
# undef /**/ HAVE_SYS_TIMES_H
|
||||
#endif
|
||||
|
||||
#if (SIZEOF_PTRDIFF_T <= 0)
|
||||
# undef /**/ SIZEOF_PTRDIFF_T
|
||||
#endif
|
||||
|
||||
#if (SIZEOF_SIZE_T <= 0)
|
||||
# undef /**/ SIZEOF_SIZE_T
|
||||
#endif
|
||||
|
||||
#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
|
||||
*/
|
||||
+4
-4
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
|
||||
+49
-6
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,14 +21,55 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
#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
|
||||
**************************************************************************/
|
||||
@@ -135,14 +176,16 @@ void throwEOFException(const char *msg, int e)
|
||||
|
||||
const char *prettyName(const char *n)
|
||||
{
|
||||
while (*n >= '0' && *n <= '9') // gcc / egcs
|
||||
if (n == NULL)
|
||||
return "";
|
||||
while (*n >= '0' && *n <= '9') // gcc
|
||||
n++;
|
||||
if (strncmp(n, "class ", 6) == 0) // Visual C++
|
||||
n += 6;
|
||||
return n;
|
||||
}
|
||||
|
||||
const char *prettyName(const type_info &ti)
|
||||
const char *prettyName(const std::type_info &ti)
|
||||
{
|
||||
return prettyName(ti.name());
|
||||
}
|
||||
|
||||
+31
-21
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
@@ -32,31 +32,41 @@
|
||||
#ifdef __cplusplus
|
||||
|
||||
const char *prettyName(const char *n);
|
||||
const char *prettyName(const type_info &ti);
|
||||
const char *prettyName(const std::type_info &ti);
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// exceptions
|
||||
**************************************************************************/
|
||||
|
||||
class Throwable : public exception
|
||||
class Throwable : public std::exception
|
||||
{
|
||||
typedef std::exception super;
|
||||
protected:
|
||||
Throwable(const char *m = 0, int e = 0, bool w = false)
|
||||
: msg(m), err(e), is_warning(w) { }
|
||||
Throwable(const char *m = 0, int e = 0, bool w = false);
|
||||
public:
|
||||
virtual ~Throwable() { }
|
||||
Throwable(Throwable const &);
|
||||
virtual ~Throwable() NOTHROW;
|
||||
const char *getMsg() const { return msg; }
|
||||
int getErrno() const { return err; }
|
||||
bool isWarning() const { return is_warning; }
|
||||
private:
|
||||
//Throwable(const Throwable &);
|
||||
private:
|
||||
// void * operator new(size_t); // ...
|
||||
const char *msg;
|
||||
char *msg;
|
||||
int err;
|
||||
protected:
|
||||
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
|
||||
#if 0 && defined(__GNUC__)
|
||||
// (noreturn) is probably not the correct semantics for throwing exceptions
|
||||
#define NORET __attribute__((noreturn))
|
||||
#define NORET __attribute__((__noreturn__))
|
||||
#else
|
||||
#define NORET
|
||||
#endif
|
||||
|
||||
void throwCantPack(const char *msg) NORET;
|
||||
void throwUnknownExecutableFormat(const char *msg = 0, bool warn = false) NORET;
|
||||
void throwNotCompressible(const char *msg = 0) NORET;
|
||||
void throwAlreadyPacked(const char *msg = 0) NORET;
|
||||
void throwAlreadyPackedByUPX(const char *msg = 0) NORET;
|
||||
void throwUnknownExecutableFormat(const char *msg = NULL, bool warn = false) NORET;
|
||||
void throwNotCompressible(const char *msg = NULL) NORET;
|
||||
void throwAlreadyPacked(const char *msg = NULL) NORET;
|
||||
void throwAlreadyPackedByUPX(const char *msg = NULL) 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 throwBadLoader() NORET;
|
||||
void throwChecksumError() NORET;
|
||||
void throwCompressedDataViolation() NORET;
|
||||
void throwInternalError(const char *msg) NORET;
|
||||
void throwIOException(const char *msg = 0, int e = 0) NORET;
|
||||
void throwEOFException(const char *msg = 0, int e = 0) NORET;
|
||||
void throwIOException(const char *msg = NULL, int e = 0) NORET;
|
||||
void throwEOFException(const char *msg = NULL, int e = 0) 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
|
||||
*/
|
||||
|
||||
+75
-39
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,13 +21,14 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.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 ok = true;
|
||||
@@ -116,9 +136,9 @@ int FileBase::read(void *buf, int len)
|
||||
for (;;)
|
||||
{
|
||||
#if 1 && defined(__DJGPP__)
|
||||
l = ::_read(_fd,buf,len);
|
||||
l = ::_read(_fd, buf, len);
|
||||
#else
|
||||
l = ::read(_fd,buf,len);
|
||||
l = ::read(_fd, buf, len);
|
||||
#endif
|
||||
if (l < 0)
|
||||
{
|
||||
@@ -136,7 +156,7 @@ int FileBase::read(void *buf, int len)
|
||||
|
||||
int FileBase::readx(void *buf, int len)
|
||||
{
|
||||
int l = this->read(buf,len);
|
||||
int l = this->read(buf, len);
|
||||
if (l != len)
|
||||
throwEOFException();
|
||||
return l;
|
||||
@@ -171,17 +191,21 @@ void FileBase::write(const void *buf, int len)
|
||||
void FileBase::seek(off_t off, int whence)
|
||||
{
|
||||
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)
|
||||
throwIOException("seek error",errno);
|
||||
}
|
||||
|
||||
|
||||
off_t FileBase::tell()
|
||||
off_t FileBase::tell() const
|
||||
{
|
||||
if (!isOpen())
|
||||
throwIOException("bad tell");
|
||||
off_t l = ::lseek(_fd,0,SEEK_CUR);
|
||||
off_t l = ::lseek(_fd, 0, SEEK_CUR);
|
||||
if (l < 0)
|
||||
throwIOException("tell error",errno);
|
||||
return l;
|
||||
@@ -209,37 +233,51 @@ void InputFile::sopen(const char *name, int flags, int shflags)
|
||||
_flags = flags;
|
||||
_shflags = shflags;
|
||||
_mode = 0;
|
||||
if (shflags < 0)
|
||||
_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
|
||||
FileBase::sopen();
|
||||
if (!isOpen())
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
throw FileNotFoundException(_name,errno);
|
||||
throw FileNotFoundException(_name, errno);
|
||||
else if (errno == EEXIST)
|
||||
throw FileAlreadyExistsException(_name,errno);
|
||||
throw FileAlreadyExistsException(_name, errno);
|
||||
else
|
||||
throwIOException(_name,errno);
|
||||
throwIOException(_name, errno);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int InputFile::read(void *buf, int len)
|
||||
{
|
||||
return super::read(buf,len);
|
||||
return super::read(buf, 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -249,7 +287,7 @@ void InputFile::seek(off_t off, int whence)
|
||||
}
|
||||
|
||||
|
||||
off_t InputFile::tell()
|
||||
off_t InputFile::tell() const
|
||||
{
|
||||
return super::tell();
|
||||
}
|
||||
@@ -277,16 +315,7 @@ void OutputFile::sopen(const char *name, int flags, int shflags, int mode)
|
||||
_flags = flags;
|
||||
_shflags = shflags;
|
||||
_mode = mode;
|
||||
if (shflags < 0)
|
||||
_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
|
||||
FileBase::sopen();
|
||||
if (!isOpen())
|
||||
{
|
||||
#if 0
|
||||
@@ -319,7 +348,9 @@ bool OutputFile::openStdout(int flags, bool force)
|
||||
if (flags != 0)
|
||||
{
|
||||
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)
|
||||
throwIOException(_name,errno);
|
||||
#if defined(__DJGPP__)
|
||||
@@ -333,7 +364,7 @@ bool OutputFile::openStdout(int flags, bool force)
|
||||
|
||||
void OutputFile::write(const void *buf, int len)
|
||||
{
|
||||
super::write(buf,len);
|
||||
super::write(buf, len);
|
||||
bytes_written += len;
|
||||
}
|
||||
|
||||
@@ -354,6 +385,8 @@ void OutputFile::dump(const char *name, const void *buf, int len, int flags)
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
#if 0
|
||||
|
||||
MemoryOutputFile::MemoryOutputFile() :
|
||||
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
|
||||
*/
|
||||
|
||||
+21
-8
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,14 +21,16 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __UPX_FILE_H
|
||||
#define __UPX_FILE_H
|
||||
|
||||
class MemBuffer;
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
@@ -56,11 +58,12 @@ public:
|
||||
const char *getName() const { return _name; }
|
||||
|
||||
protected:
|
||||
void sopen();
|
||||
virtual int read(void *buf, int len);
|
||||
virtual int readx(void *buf, int len);
|
||||
virtual void write(const void *buf, int len);
|
||||
virtual void seek(off_t off, int whence);
|
||||
virtual off_t tell();
|
||||
virtual off_t tell() const;
|
||||
|
||||
int _fd;
|
||||
int _flags;
|
||||
@@ -89,11 +92,15 @@ public:
|
||||
sopen(name, flags, -1);
|
||||
}
|
||||
|
||||
virtual int read(void * buf, int len);
|
||||
virtual int readx(void * buf, int len);
|
||||
virtual int read(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 off_t tell();
|
||||
virtual off_t tell() const;
|
||||
};
|
||||
|
||||
|
||||
@@ -119,16 +126,20 @@ public:
|
||||
|
||||
off_t getBytesWritten() const { return bytes_written; }
|
||||
|
||||
#if (UPX_VERSION_HEX >= 0x019000)
|
||||
// FIXME - these won't work when using the `--stdout' option
|
||||
virtual void seek(off_t off, int whence)
|
||||
{
|
||||
assert(!opt->to_stdout);
|
||||
super::seek(off,whence);
|
||||
}
|
||||
virtual void rewrite(const void *buf, int len)
|
||||
{
|
||||
assert(!opt->to_stdout);
|
||||
write(buf, len);
|
||||
bytes_written -= len; // restore
|
||||
}
|
||||
#endif
|
||||
|
||||
// util
|
||||
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
|
||||
{
|
||||
typedef FileBase super;
|
||||
@@ -164,6 +176,7 @@ protected:
|
||||
unsigned b_pos;
|
||||
off_t bytes_written;
|
||||
};
|
||||
#endif /* if 0 */
|
||||
|
||||
|
||||
#endif /* already included */
|
||||
|
||||
+26
-22
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,13 +21,14 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.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_len = buf_len;
|
||||
// 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
|
||||
**************************************************************************/
|
||||
@@ -88,10 +96,10 @@ void Filter::init(int id_, unsigned addvalue_)
|
||||
initFilter(this, NULL, 0);
|
||||
// clear input parameters
|
||||
this->addvalue = addvalue_;
|
||||
this->forced_cto = -1;
|
||||
this->preferred_ctos = NULL;
|
||||
// clear input/output parameters
|
||||
this->cto = 0;
|
||||
this->n_mru = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -112,13 +120,12 @@ bool Filter::filter(upx_byte *buf_, unsigned buf_len_)
|
||||
throwInternalError("filter-2");
|
||||
|
||||
// save checksum
|
||||
this->adler = 0;
|
||||
if (clevel != 1)
|
||||
{
|
||||
this->adler = upx_adler32(0,NULL,0);
|
||||
this->adler = upx_adler32(this->adler, this->buf, this->buf_len);
|
||||
}
|
||||
this->adler = upx_adler32(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);
|
||||
//printf("filter: %02x %d\n", fe->id, r);
|
||||
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_);
|
||||
|
||||
@@ -137,11 +144,11 @@ bool Filter::unfilter(upx_byte *buf_, unsigned buf_len_, bool verify_checksum)
|
||||
if (fe == NULL)
|
||||
throwInternalError("unfilter-1");
|
||||
if (fe->id == 0)
|
||||
return true;
|
||||
return;
|
||||
if (buf_len < fe->min_buf_len)
|
||||
return false;
|
||||
return;
|
||||
if (fe->max_buf_len && buf_len > fe->max_buf_len)
|
||||
return false;
|
||||
return;
|
||||
if (!fe->do_unfilter)
|
||||
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);
|
||||
if (r != 0)
|
||||
throwInternalError("unfilter-3");
|
||||
//OutputFile::dump("unfilter.dat", buf, buf_len);
|
||||
|
||||
// verify checksum
|
||||
if (verify_checksum && clevel != 1)
|
||||
{
|
||||
unsigned a = upx_adler32(0,NULL,0);
|
||||
if (this->adler != upx_adler32(a, this->buf, this->buf_len))
|
||||
if (this->adler != upx_adler32(this->buf, this->buf_len))
|
||||
throwInternalError("unfilter-4");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Filter::verifyUnfilter()
|
||||
void Filter::verifyUnfilter()
|
||||
{
|
||||
// Note:
|
||||
// This verify is just because of complete paranoia that there
|
||||
@@ -175,9 +180,8 @@ bool Filter::verifyUnfilter()
|
||||
// Packer::verifyOverlappingDecompression()
|
||||
|
||||
//printf("verifyUnfilter: %02x %p %d\n", this->id, this->buf, this->buf_len);
|
||||
if (clevel == 1)
|
||||
return true;
|
||||
return unfilter(this->buf, this->buf_len, true);
|
||||
if (clevel != 1)
|
||||
unfilter(this->buf, this->buf_len, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+11
-9
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
@@ -44,8 +44,7 @@ class FilterImp;
|
||||
// call throwFilterException() - this will cause the compression
|
||||
// to fail.
|
||||
//
|
||||
// The return value of unfilters can/should be ignored. They throw
|
||||
// exceptions in case of errors.
|
||||
// Unfilters throw exceptions in case of errors.
|
||||
//
|
||||
// The main idea behind filters is to convert relative jumps and calls
|
||||
// to absolute addresses so that the buffer compresses better.
|
||||
@@ -58,10 +57,12 @@ public:
|
||||
void init(int id=0, unsigned addvalue=0);
|
||||
|
||||
bool filter(upx_byte *buf, unsigned buf_len);
|
||||
bool unfilter(upx_byte *buf, unsigned buf_len, bool verify_checksum=false);
|
||||
bool verifyUnfilter();
|
||||
void unfilter(upx_byte *buf, unsigned buf_len, bool verify_checksum=false);
|
||||
void verifyUnfilter();
|
||||
bool scan(const upx_byte *buf, unsigned buf_len);
|
||||
|
||||
static bool isValidFilter(int filter_id);
|
||||
|
||||
public:
|
||||
// Will be set by each call to filter()/unfilter().
|
||||
// Read-only afterwards.
|
||||
@@ -74,7 +75,6 @@ public:
|
||||
|
||||
// Input parameters used by various filters.
|
||||
unsigned addvalue;
|
||||
int forced_cto;
|
||||
const int *preferred_ctos;
|
||||
|
||||
// Input/output parameters used by various filters
|
||||
@@ -84,7 +84,9 @@ public:
|
||||
unsigned calls;
|
||||
unsigned noncalls;
|
||||
unsigned wrongcalls;
|
||||
unsigned firstcall;
|
||||
unsigned lastcall;
|
||||
unsigned n_mru; // ctojr only
|
||||
|
||||
// Read only.
|
||||
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.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,14 +21,14 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
// filter / scan
|
||||
**************************************************************************/
|
||||
|
||||
static int F(Filter *f)
|
||||
@@ -44,64 +44,27 @@ static int F(Filter *f)
|
||||
const unsigned size = f->buf_len;
|
||||
|
||||
unsigned ic, jc, kc;
|
||||
unsigned cto;
|
||||
unsigned char cto8;
|
||||
unsigned calls = 0, noncalls = 0, noncalls2 = 0;
|
||||
unsigned lastnoncall = size, lastcall = 0;
|
||||
|
||||
// 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];
|
||||
memset(buf,0,256);
|
||||
|
||||
#if 1
|
||||
for (ic = 0; ic < size - 5; ic++)
|
||||
if (COND(b,ic) && get_le32(b+ic+1)+ic+1 >= size)
|
||||
{
|
||||
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 (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");
|
||||
if (getcto(f, buf) < 0)
|
||||
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++)
|
||||
{
|
||||
@@ -145,7 +108,6 @@ static int F(Filter *f)
|
||||
}
|
||||
}
|
||||
|
||||
f->cto = cto8;
|
||||
f->calls = calls;
|
||||
f->noncalls = noncalls;
|
||||
f->lastcall = lastcall;
|
||||
@@ -157,13 +119,17 @@ static int F(Filter *f)
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// 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 = f->cto << 24;
|
||||
const unsigned cto = (unsigned)f->cto << 24;
|
||||
|
||||
unsigned ic, jc;
|
||||
|
||||
@@ -186,7 +152,11 @@ static int U(Filter *f)
|
||||
#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.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
Copyright (C) 2000 John F. Reiser
|
||||
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
|
||||
@@ -22,14 +22,17 @@
|
||||
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
|
||||
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)
|
||||
@@ -45,64 +48,27 @@ static int F(Filter *f)
|
||||
const unsigned size = f->buf_len;
|
||||
|
||||
unsigned ic, jc, kc;
|
||||
unsigned cto;
|
||||
unsigned char cto8;
|
||||
unsigned calls = 0, noncalls = 0, noncalls2 = 0;
|
||||
unsigned lastnoncall = size, lastcall = 0;
|
||||
|
||||
// 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];
|
||||
memset(buf,0,256);
|
||||
|
||||
#if 1
|
||||
for (ic = 0; ic < size - 5; ic++)
|
||||
if (COND(b,ic,lastcall) && get_le32(b+ic+1)+ic+1 >= size)
|
||||
{
|
||||
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 (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");
|
||||
if (getcto(f, buf) < 0)
|
||||
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++)
|
||||
{
|
||||
@@ -146,7 +112,6 @@ static int F(Filter *f)
|
||||
}
|
||||
}
|
||||
|
||||
f->cto = cto8;
|
||||
f->calls = calls;
|
||||
f->noncalls = noncalls;
|
||||
f->lastcall = lastcall;
|
||||
@@ -158,13 +123,17 @@ static int F(Filter *f)
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// 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 = f->cto << 24;
|
||||
const unsigned cto = (unsigned)f->cto << 24;
|
||||
unsigned lastcall = 0;
|
||||
|
||||
unsigned ic, jc;
|
||||
@@ -188,7 +157,11 @@ static int U(Filter *f)
|
||||
#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
|
||||
*/
|
||||
|
||||
+155
-366
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
@@ -31,375 +31,118 @@
|
||||
|
||||
|
||||
#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) \
|
||||
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
|
||||
#include "filter/getcto.h"
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// 32-bit calltrick ("naive")
|
||||
// simple filters: calltrick / swaptrick / delta / ...
|
||||
**************************************************************************/
|
||||
|
||||
#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;
|
||||
#include "filter/ct.h"
|
||||
#include "filter/sw.h"
|
||||
#include "filter/ctsw.h"
|
||||
|
||||
|
||||
// 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
|
||||
|
||||
#undef set_dummy
|
||||
#include "filter/sub8.h"
|
||||
#include "filter/sub16.h"
|
||||
#include "filter/sub32.h"
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// 32-bit calltrick with cto ("clever")
|
||||
//
|
||||
// This version is more sophisticated because it only
|
||||
// tries to change actual calls and/or jumps.
|
||||
// cto calltrick
|
||||
**************************************************************************/
|
||||
|
||||
#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[] = {
|
||||
// no filter
|
||||
{ 0x00, 0, 0, NULL, NULL, NULL },
|
||||
|
||||
// 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 },
|
||||
{ 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 },
|
||||
@@ -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 },
|
||||
{ 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 },
|
||||
|
||||
// 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
|
||||
{ 0x11, 6, 0, f_ct32_e8, u_ct32_e8, s_ct32_e8 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
|
||||
// 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
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 0x29, 6, 0x00ffffff, f_cto32_e8e9_bswap_be, u_cto32_e8e9_bswap_be, s_cto32_e8e9_bswap_be },
|
||||
// 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 cto calltrick with jmp
|
||||
{ 0x36, 6, 0x00ffffff, f_ctoj32_e8e9_bswap_le, u_ctoj32_e8e9_bswap_le, s_ctoj32_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);
|
||||
|
||||
+100
-35
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
@@ -44,13 +44,24 @@ void show_head(void)
|
||||
return;
|
||||
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);
|
||||
con_fprintf(f,
|
||||
" Ultimate Packer for eXecutables\n"
|
||||
" Copyright (C) 1996, 1997, 1998, 1999, 2000\n"
|
||||
"UPX v%-12sMarkus F.X.J. Oberhumer & Laszlo Molnar%21s\n\n",
|
||||
UPX_VERSION_STRING, UPX_VERSION_DATE);
|
||||
" Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002\n"
|
||||
"UPX %-12s Markus F.X.J. Oberhumer & Laszlo Molnar %20s\n\n",
|
||||
#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);
|
||||
#undef V
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +73,7 @@ void show_usage(void)
|
||||
{
|
||||
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__)
|
||||
"[@]");
|
||||
#else
|
||||
@@ -101,7 +112,6 @@ void show_help(int x)
|
||||
|
||||
con_fprintf(f,
|
||||
" -q be quiet -v be verbose\n"
|
||||
//" -oFILE write output to `FILE' -c write output to stdout\n"
|
||||
" -oFILE write output to `FILE'\n"
|
||||
//" -f force overwrite of output files and 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=skip don't compress a file with an overlay\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);
|
||||
con_fprintf(f,"Options for djgpp2/coff:\n");
|
||||
fg = con_fg(f,fg);
|
||||
con_fprintf(f,
|
||||
" --coff produce COFF output [default: EXE]\n"
|
||||
" --all-methods try all available compression methods\n"
|
||||
" --all-filters try all available preprocessing filters\n"
|
||||
"\n");
|
||||
fg = con_fg(f,FG_YELLOW);
|
||||
con_fprintf(f,"Options for dos/com:\n");
|
||||
fg = con_fg(f,fg);
|
||||
con_fprintf(f,
|
||||
" --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");
|
||||
fg = con_fg(f,FG_YELLOW);
|
||||
con_fprintf(f,"Options for dos/exe:\n");
|
||||
@@ -149,13 +171,52 @@ void show_help(int x)
|
||||
con_fprintf(f,
|
||||
" --8086 make compressed exe work on any 8086\n"
|
||||
" --no-reloc put no relocations in to the exe header\n"
|
||||
" --all-methods try all available compression methods\n"
|
||||
"\n");
|
||||
fg = con_fg(f,FG_YELLOW);
|
||||
con_fprintf(f,"Options for dos/sys:\n");
|
||||
fg = con_fg(f,fg);
|
||||
con_fprintf(f,
|
||||
" --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");
|
||||
#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);
|
||||
con_fprintf(f,"Options for watcom/le:\n");
|
||||
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"
|
||||
" --strip-relocs=0 do not strip relocations\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");
|
||||
#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,
|
||||
" file.. executables to (de)compress\n"
|
||||
"\n"
|
||||
"This version supports:\n "
|
||||
"file.. executables to (de)compress\n"
|
||||
"\n");
|
||||
fg = con_fg(f,FG_YELLOW);
|
||||
con_fprintf(f,"This version supports:\n");
|
||||
fg = con_fg(f,fg);
|
||||
con_fprintf(f," "
|
||||
"atari/tos, "
|
||||
"bvmlinuz/386, "
|
||||
"djgpp2/coff, "
|
||||
"dos/com, "
|
||||
"dos/exe, "
|
||||
"dos/sys,\n "
|
||||
//"elks/8086, "
|
||||
"linux/386, "
|
||||
"linux/elf386, "
|
||||
"linux/sh386, "
|
||||
"ps1/exe, "
|
||||
"rtm32/pe, "
|
||||
"tmt/adam, "
|
||||
"vmlinuz/386,\n "
|
||||
"tmt/adam,\n "
|
||||
"vmlinuz/386, "
|
||||
"watcom/le, "
|
||||
//"win16/ne, "
|
||||
"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"
|
||||
"");
|
||||
|
||||
@@ -234,7 +294,7 @@ void show_license(void)
|
||||
|
||||
show_head();
|
||||
|
||||
con_fprintf(f,
|
||||
con_fprintf(f,
|
||||
" This program may be used freely, and you are welcome to\n"
|
||||
" redistribute it under certain conditions.\n"
|
||||
"\n"
|
||||
@@ -249,15 +309,15 @@ con_fprintf(f,
|
||||
"\n"
|
||||
);
|
||||
int fg = con_fg(f,FG_CYAN);
|
||||
con_fprintf(f,
|
||||
" http://upx.tsx.org\n"
|
||||
" http://wildsau.idv.uni-linz.ac.at/mfx/upx.html\n"
|
||||
con_fprintf(f,
|
||||
" http://upx.sourceforge.net\n"
|
||||
" http://www.oberhumer.com/opensource/upx/\n"
|
||||
);
|
||||
(void)con_fg(f,FG_ORANGE);
|
||||
con_fprintf(f,
|
||||
con_fprintf(f,
|
||||
"\n"
|
||||
" Markus F.X.J. Oberhumer Laszlo Molnar\n"
|
||||
" markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu\n"
|
||||
" Markus F.X.J. Oberhumer Laszlo Molnar\n"
|
||||
" <mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>\n"
|
||||
);
|
||||
fg = con_fg(f,fg);
|
||||
}
|
||||
@@ -272,16 +332,21 @@ void show_version(int x)
|
||||
FILE *f = stdout;
|
||||
UNUSED(x);
|
||||
|
||||
fprintf(f,"upx %s\n",UPX_VERSION_STRING);
|
||||
#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);
|
||||
#endif
|
||||
#if defined(WITH_NRV)
|
||||
fprintf(f,"NRV data compression library %s\n", nrv_version_string());
|
||||
#endif
|
||||
#if defined(WITH_UCL)
|
||||
fprintf(f,"UCL data compression library %s\n", ucl_version_string());
|
||||
#endif
|
||||
fprintf(f,"Copyright (C) 1996,1997,1998,1999,2000 Markus Franz Xaver Johannes Oberhumer\n");
|
||||
fprintf(f,"Copyright (C) 1996,1997,1998,1999,2000 Laszlo Molnar\n");
|
||||
fprintf(f,"Copyright (C) 2000 John F. Reiser\n");
|
||||
fprintf(f,"Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer\n");
|
||||
fprintf(f,"Copyright (C) 1996-2002 Laszlo Molnar\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);
|
||||
}
|
||||
|
||||
|
||||
+29
-12
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
@@ -32,8 +32,13 @@
|
||||
#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(&oh,0,sizeof oh);
|
||||
iobject_table = oobject_table = NULL;
|
||||
@@ -43,7 +48,6 @@ LeFile::LeFile(InputFile *f) : fif(f)
|
||||
ifixups = ofixups = NULL;
|
||||
inonres_names = ononres_names = 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()
|
||||
{
|
||||
soimage = pages*mps;
|
||||
@@ -295,7 +311,8 @@ void LeFile::writeFile(OutputFile *f, bool le)
|
||||
|
||||
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[objects] - # of selector fixups
|
||||
// counts[objects+1] - # of self-relative fixups
|
||||
@@ -311,7 +328,7 @@ void LeFile::countFixups(unsigned *counts) const
|
||||
switch (*fix)
|
||||
{
|
||||
case 2: // selector fixup
|
||||
counts[objects] += 9;
|
||||
counts[o] += 9;
|
||||
fix += 5;
|
||||
break;
|
||||
case 0x12: // alias selector
|
||||
@@ -320,7 +337,7 @@ void LeFile::countFixups(unsigned *counts) const
|
||||
fix += (fix[1] & 0x10) ? 9 : 7;
|
||||
break;
|
||||
case 6: // 16:32 pointer
|
||||
counts[objects] += 9;
|
||||
counts[o] += 9;
|
||||
case 7: // 32-bit offset
|
||||
counts[fix[4]-1] += 4;
|
||||
fix += (fix[1] & 0x10) ? 9 : 7;
|
||||
@@ -332,15 +349,15 @@ void LeFile::countFixups(unsigned *counts) const
|
||||
fix += ll*2;
|
||||
break;
|
||||
case 8: // 32-bit self relative fixup
|
||||
counts[objects+1] += 4;
|
||||
counts[o+1] += 4;
|
||||
fix += (fix[1] & 0x10) ? 9 : 7;
|
||||
break;
|
||||
default:
|
||||
throwCantPack("unsupported fixup record");
|
||||
}
|
||||
}
|
||||
counts[objects]++; // extra space for 'ret'
|
||||
counts[objects+1] += 4; // extra space for 0xFFFFFFFF
|
||||
counts[o]++; // extra space for 'ret'
|
||||
counts[o+1] += 4; // extra space for 0xFFFFFFFF
|
||||
}
|
||||
|
||||
|
||||
|
||||
+15
-11
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
@@ -117,7 +117,8 @@ protected:
|
||||
LE16 device_id;
|
||||
LE16 ddk_version;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
struct le_object_table_entry_t
|
||||
{
|
||||
@@ -127,15 +128,17 @@ protected:
|
||||
LE32 pagemap_index;
|
||||
LE32 npages;
|
||||
LE32 reserved;
|
||||
};
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
struct le_pagemap_entry_t
|
||||
{
|
||||
upx_byte h;
|
||||
upx_byte m;
|
||||
upx_byte l;
|
||||
upx_byte type; // 0x00-legal;0x40-iterated;0x80-invalid;0xC0-zeroed
|
||||
};
|
||||
unsigned char h;
|
||||
unsigned char m;
|
||||
unsigned char l;
|
||||
unsigned char type; // 0x00-legal;0x40-iterated;0x80-invalid;0xC0-zeroed
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
virtual void readObjectTable();
|
||||
virtual void writeObjectTable();
|
||||
@@ -178,6 +181,7 @@ protected:
|
||||
//virtual void decodeImage(){encodeImage();}
|
||||
|
||||
void countFixups(unsigned *) const;
|
||||
unsigned getImageSize() const;
|
||||
|
||||
InputFile *fif;
|
||||
OutputFile *fof;
|
||||
|
||||
+30
-20
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
@@ -46,7 +46,6 @@ struct Linker::jump
|
||||
int toffs;
|
||||
};
|
||||
|
||||
|
||||
Linker::Linker(const void *pdata, int plen, int pinfo)
|
||||
{
|
||||
iloader = new char[(ilen = plen) + 4096];
|
||||
@@ -54,18 +53,19 @@ Linker::Linker(const void *pdata, int plen, int pinfo)
|
||||
oloader = new char[plen];
|
||||
olen = 0;
|
||||
align_hack = 0;
|
||||
align_offset = 0;
|
||||
info = pinfo;
|
||||
njumps = nsections = frozen = 0;
|
||||
jumps = new jump[200];
|
||||
sections = new section[200];
|
||||
|
||||
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);
|
||||
sections[nsections].istart = get_le32(p+8);
|
||||
sections[nsections].istart = get32(p+8);
|
||||
sections[nsections++].ostart = -1;
|
||||
p += 12;
|
||||
assert(nsections < 200);
|
||||
@@ -73,13 +73,13 @@ Linker::Linker(const void *pdata, int plen, int pinfo)
|
||||
else
|
||||
{
|
||||
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].len = get_le32(p+4)-jumps[njumps].pos;
|
||||
jumps[njumps].len = get32(p+4)-jumps[njumps].pos;
|
||||
memcpy(jumps[njumps].tsect,p+8,8);
|
||||
jumps[njumps++].toffs = get_le32(p+16);
|
||||
jumps[njumps++].toffs = get32(p+16);
|
||||
p += 20;
|
||||
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;
|
||||
while (*sect)
|
||||
@@ -109,14 +119,13 @@ void Linker::addSection(const char *sect)
|
||||
if (*sect == '+') // alignment
|
||||
{
|
||||
if (sect[1] == '0')
|
||||
align_hack = olen;
|
||||
align_hack = olen + align_offset;
|
||||
else
|
||||
{
|
||||
ic = (sect[1] & 0xf) + (sect[1] > '9' ? 9 : 0);
|
||||
ic = (ic + (sect[2] & 0xf) + (sect[2] > '9' ? 9 : 0)
|
||||
- (olen - align_hack) % ic) % ic;
|
||||
memset(oloader+olen,sect[3] == 'C' ? 0x90 : 0,ic);
|
||||
olen += ic;
|
||||
unsigned j = hex(sect[1]);
|
||||
j = (hex(sect[2]) - ((olen + align_offset) - align_hack) ) % j;
|
||||
memset(oloader+olen, (sect[3] == 'C' ? 0x90 : 0), j);
|
||||
olen += j;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -129,11 +138,12 @@ void Linker::addSection(const char *sect)
|
||||
olen += sections[ic].len;
|
||||
break;
|
||||
}
|
||||
//printf("%8.8s",section);
|
||||
//printf("%8.8s",sect);
|
||||
assert(ic!=nsections);
|
||||
}
|
||||
sect += 8;
|
||||
}
|
||||
return olen;
|
||||
}
|
||||
|
||||
|
||||
@@ -177,7 +187,7 @@ const char *Linker::getLoader(int *llen)
|
||||
if (jumps[ic].len == 1)
|
||||
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);
|
||||
}
|
||||
frozen=1;
|
||||
|
||||
+32
-6
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
@@ -34,11 +34,18 @@ class Linker
|
||||
{
|
||||
public:
|
||||
Linker(const void *pdata, int plen, int pinfo);
|
||||
~Linker();
|
||||
void addSection(const char *sect);
|
||||
virtual ~Linker();
|
||||
int addSection(const char *sect);
|
||||
void addSection(const char *sname, const void *sdata, unsigned len);
|
||||
const char *getLoader(int *llen);
|
||||
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:
|
||||
struct section;
|
||||
@@ -53,6 +60,7 @@ private:
|
||||
int nsections;
|
||||
int frozen;
|
||||
int align_hack;
|
||||
int align_offset;
|
||||
|
||||
private:
|
||||
// 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 */
|
||||
|
||||
|
||||
+200
-79
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,14 +21,21 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
#include "mygetopt.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->method = -1;
|
||||
o->level = -1;
|
||||
o->mem_level = -1;
|
||||
o->filter = -1;
|
||||
|
||||
o->backup = -1;
|
||||
@@ -59,7 +65,10 @@ void init_options(struct options_t *o)
|
||||
|
||||
o->w32pe.compress_exports = 1;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
void e_envopt(const char *n)
|
||||
{
|
||||
@@ -228,6 +245,11 @@ void check_options(int i, int argc)
|
||||
opt->backup = 1;
|
||||
|
||||
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 (i + 1 != argc)
|
||||
@@ -270,7 +292,12 @@ static void set_cmd(int cmd)
|
||||
static bool set_method(int m, int l)
|
||||
{
|
||||
if (m > 0)
|
||||
{
|
||||
if (!Packer::isValidCompressionMethod(m))
|
||||
return false;
|
||||
opt->method = m;
|
||||
opt->all_methods = false;
|
||||
}
|
||||
if (l > 0)
|
||||
opt->level = l;
|
||||
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);
|
||||
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);
|
||||
e_usage();
|
||||
@@ -403,10 +430,13 @@ static int do_option(int optc, const char *arg)
|
||||
|
||||
switch (optc)
|
||||
{
|
||||
#if 0
|
||||
// FIXME: to_stdout doesn't work because of console code mess
|
||||
//case 'c':
|
||||
case 517:
|
||||
opt->to_stdout = true;
|
||||
break;
|
||||
#endif
|
||||
case 'd':
|
||||
set_cmd(CMD_DECOMPRESS);
|
||||
break;
|
||||
@@ -416,7 +446,7 @@ static int do_option(int optc, const char *arg)
|
||||
case 'f':
|
||||
opt->force++;
|
||||
break;
|
||||
case 901:
|
||||
case 902:
|
||||
set_cmd(CMD_FILEINFO);
|
||||
break;
|
||||
case 'h':
|
||||
@@ -425,9 +455,11 @@ static int do_option(int optc, const char *arg)
|
||||
set_cmd(CMD_HELP);
|
||||
break;
|
||||
case 'h'+256:
|
||||
#if 0
|
||||
/* according to GNU standards */
|
||||
set_term(stdout);
|
||||
opt->console = CON_FILE;
|
||||
#endif
|
||||
show_help(1);
|
||||
e_exit(EXIT_OK);
|
||||
break;
|
||||
@@ -472,6 +504,10 @@ static int do_option(int optc, const char *arg)
|
||||
if (!set_method(M_NRV2D_LE32, -1))
|
||||
e_method(M_NRV2D_LE32, opt->level);
|
||||
break;
|
||||
case 705:
|
||||
if (!set_method(M_NRV2E_LE32, -1))
|
||||
e_method(M_NRV2E_LE32, opt->level);
|
||||
break;
|
||||
|
||||
// compression level
|
||||
case '1':
|
||||
@@ -486,16 +522,18 @@ static int do_option(int optc, const char *arg)
|
||||
if (!set_method(-1, optc - '0'))
|
||||
e_method(opt->method, optc);
|
||||
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))
|
||||
e_method(opt->method, 10);
|
||||
break;
|
||||
|
||||
// compression memory level
|
||||
case 902:
|
||||
getoptvar(&opt->mem_level, 1, 9);
|
||||
break;
|
||||
|
||||
// misc
|
||||
case 512:
|
||||
opt->console = CON_FILE;
|
||||
@@ -513,17 +551,27 @@ static int do_option(int optc, const char *arg)
|
||||
opt->no_env = true;
|
||||
break;
|
||||
// compression settings
|
||||
case 525:
|
||||
opt->small = 1;
|
||||
case 520: // --small
|
||||
if (opt->small < 0)
|
||||
opt->small = 0;
|
||||
opt->small++;
|
||||
break;
|
||||
case 526:
|
||||
case 521: // --filter=
|
||||
getoptvar(&opt->filter, 0, 255);
|
||||
opt->all_filters = false;
|
||||
break;
|
||||
case 527:
|
||||
case 522: // --no-filter
|
||||
opt->filter = 0;
|
||||
opt->all_filters = false;
|
||||
break;
|
||||
case 523: // --all-filters
|
||||
opt->all_filters = true;
|
||||
opt->filter = -1;
|
||||
break;
|
||||
case 524: // --all-methods
|
||||
opt->all_methods = true;
|
||||
opt->method = -1;
|
||||
break;
|
||||
// compression parms
|
||||
case 531:
|
||||
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);
|
||||
break;
|
||||
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;
|
||||
// backup
|
||||
case 'k':
|
||||
@@ -636,10 +685,19 @@ static int do_option(int optc, const char *arg)
|
||||
getoptvar(&opt->unix.blocksize, 8192u, ~0u);
|
||||
break;
|
||||
case 661:
|
||||
opt->unix.force_execve = true;
|
||||
break;
|
||||
case 662:
|
||||
opt->unix.script_name = "/usr/local/lib/upx/upxX";
|
||||
if (mfx_optarg && mfx_optarg[0])
|
||||
set_script_name(mfx_optarg,1);
|
||||
break;
|
||||
case 663:
|
||||
opt->unix.ptinterp = true;
|
||||
break;
|
||||
case 670:
|
||||
opt->ps1.no_align = true;
|
||||
break;
|
||||
|
||||
case '\0':
|
||||
return -1;
|
||||
@@ -661,10 +719,11 @@ static int get_options(int argc, char **argv)
|
||||
static const struct mfx_option longopts[] =
|
||||
{
|
||||
// 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
|
||||
{"fast", 0, 0, '1'}, // compress faster
|
||||
{"fileinfo", 0x10, 0, 901}, // display info about file
|
||||
{"fast", 0x10, 0, '1'}, // compress faster
|
||||
{"fileinfo", 0x10, 0, 902}, // display info about file
|
||||
{"help", 0, 0, 'h'+256}, // give help
|
||||
{"license", 0, 0, 'L'}, // display software license
|
||||
{"list", 0, 0, 'l'}, // list compressed exe
|
||||
@@ -682,8 +741,11 @@ static const struct mfx_option longopts[] =
|
||||
{"output", 0x21, 0, 'o'},
|
||||
{"quiet", 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
|
||||
{"to-stdout", 0x10, 0, 517}, // write output on standard output
|
||||
#endif
|
||||
{"verbose", 0, 0, 'v'}, // verbose mode
|
||||
|
||||
// backup options
|
||||
@@ -710,17 +772,15 @@ static const struct mfx_option longopts[] =
|
||||
{"color", 0, 0, 514},
|
||||
|
||||
// compression method
|
||||
{"2b", 0x10, 0, 702}, // --2b
|
||||
{"n2b", 0x10, 0, 702}, // --n2b
|
||||
{"nrv2b", 0x10, 0, 702}, // --nrv2b
|
||||
{"2d", 0x10, 0, 704}, // --2d
|
||||
{"n2d", 0x10, 0, 704}, // --n2d
|
||||
{"nrv2d", 0x10, 0, 704}, // --nrv2d
|
||||
{"nrv2e", 0x10, 0, 705}, // --nrv2e
|
||||
// compression settings
|
||||
{"all-filters", 0x10, 0, 527},
|
||||
{"filter", 0x31, 0, 526}, // --filter=
|
||||
{"mem", 0x31, 0, 902}, // --mem=
|
||||
{"small", 0x10, 0, 525},
|
||||
{"all-filters", 0x10, 0, 523},
|
||||
{"all-methods", 0x10, 0, 524},
|
||||
{"filter", 0x31, 0, 521}, // --filter=
|
||||
{"no-filter", 0x10, 0, 522},
|
||||
{"small", 0x10, 0, 520},
|
||||
// compression runtime parameters
|
||||
{"crp-cf", 0x31, 0, 531},
|
||||
{"crp-sl", 0x31, 0, 532},
|
||||
@@ -741,9 +801,11 @@ static const struct mfx_option longopts[] =
|
||||
// dos/sys
|
||||
// unix
|
||||
{"blocksize", 0x31, 0, 660}, // --blocksize=
|
||||
{"force-execve", 0x10, 0, 661}, // force linux/386 execve format
|
||||
#if 0
|
||||
{"script", 0x31, 0, 661}, // --script=
|
||||
{"script", 0x31, 0, 662}, // --script=
|
||||
#endif
|
||||
{"ptinterp", 0, 0, 663}, // linux/elf386 PT_INTERP program
|
||||
// watcom/le
|
||||
{"le", 0, 0, 620}, // produce LE output
|
||||
// win32/pe
|
||||
@@ -751,8 +813,10 @@ static const struct mfx_option longopts[] =
|
||||
{"compress-icons", 2, 0, 631},
|
||||
{"compress-resources", 2, 0, 632},
|
||||
{"strip-relocs", 2, 0, 633},
|
||||
// ps1/exe
|
||||
{"no-align", 0x10, 0, 670},
|
||||
|
||||
{ 0, 0, 0, 0 }
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
int optc, longind;
|
||||
@@ -780,8 +844,9 @@ static void get_envoptions(int argc, char **argv)
|
||||
static const struct mfx_option longopts[] =
|
||||
{
|
||||
// commands
|
||||
{"best", 0, 0, 900}, // compress best
|
||||
{"fast", 0, 0, '1'}, // compress faster
|
||||
{"best", 0x10, 0, 900}, // compress best
|
||||
{"brute", 0x10, 0, 901}, // compress best, brute force
|
||||
{"fast", 0x10, 0, '1'}, // compress faster
|
||||
|
||||
// options
|
||||
{"info", 0, 0, 'i'}, // info mode
|
||||
@@ -819,7 +884,7 @@ static const struct mfx_option longopts[] =
|
||||
{"compress-resources", 2, 0, 632},
|
||||
{"strip-relocs", 2, 0, 633},
|
||||
|
||||
{ 0, 0, 0, 0 }
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
char *env, *p;
|
||||
@@ -907,14 +972,22 @@ static const struct mfx_option longopts[] =
|
||||
static void first_options(int argc, char **argv)
|
||||
{
|
||||
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)
|
||||
do_option('V'+256, argv[i]);
|
||||
for (i = 1; i < argc; i++)
|
||||
}
|
||||
for (i = 1; i < n; i++)
|
||||
if (strcmp(argv[i],"--help") == 0)
|
||||
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)
|
||||
do_option(519, argv[i]);
|
||||
}
|
||||
@@ -926,57 +999,101 @@ static void first_options(int argc, char **argv)
|
||||
|
||||
void upx_sanity_check(void)
|
||||
{
|
||||
assert(sizeof(char) == 1);
|
||||
assert(sizeof(short) == 2);
|
||||
assert(sizeof(int) == 4);
|
||||
assert(sizeof(long) >= 4);
|
||||
assert(sizeof(void *) >= 4);
|
||||
assert(sizeof(long) >= sizeof(void *));
|
||||
assert(((size_t) -1) > 0);
|
||||
assert(((ptrdiff_t) -1) < 0);
|
||||
assert(((off_t) -1) < 0);
|
||||
COMPILE_TIME_ASSERT(sizeof(char) == 1);
|
||||
COMPILE_TIME_ASSERT(sizeof(short) == 2);
|
||||
COMPILE_TIME_ASSERT(sizeof(int) == 4);
|
||||
COMPILE_TIME_ASSERT(sizeof(long) >= 4);
|
||||
COMPILE_TIME_ASSERT(sizeof(void *) >= 4);
|
||||
COMPILE_TIME_ASSERT(sizeof(long) >= sizeof(void *));
|
||||
|
||||
assert(sizeof(BE16) == 2);
|
||||
assert(sizeof(BE32) == 4);
|
||||
assert(sizeof(LE16) == 2);
|
||||
assert(sizeof(LE32) == 4);
|
||||
COMPILE_TIME_ASSERT(sizeof(upx_int64l) >= 8);
|
||||
COMPILE_TIME_ASSERT(sizeof(upx_int64l) >= sizeof(long));
|
||||
COMPILE_TIME_ASSERT(sizeof(upx_int64l) == sizeof(upx_uint64l));
|
||||
|
||||
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 foo_t {
|
||||
char c1;
|
||||
LE16 v[4];
|
||||
} d[3];
|
||||
};
|
||||
} __attribute_packed;
|
||||
foo_t d[3];
|
||||
} __attribute_packed;
|
||||
struct align_assertion_1b_t
|
||||
{
|
||||
struct foo_t {
|
||||
char c1;
|
||||
char v[4*2];
|
||||
} d[3];
|
||||
};
|
||||
} __attribute_packed;
|
||||
foo_t d[3];
|
||||
} __attribute_packed;
|
||||
struct align_assertion_2a_t
|
||||
{
|
||||
struct foo_t {
|
||||
char c1;
|
||||
LE32 v[4];
|
||||
} d[3];
|
||||
};
|
||||
} __attribute_packed;
|
||||
foo_t d[3];
|
||||
} __attribute_packed;
|
||||
struct align_assertion_2b_t
|
||||
{
|
||||
struct foo_t {
|
||||
char c1;
|
||||
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_1b_t));
|
||||
//printf("%d\n", (int) sizeof(align_assertion_2a_t));
|
||||
//printf("%d\n", (int) sizeof(align_assertion_2b_t));
|
||||
assert(sizeof(align_assertion_1a_t) == sizeof(align_assertion_1b_t));
|
||||
assert(sizeof(align_assertion_2a_t) == sizeof(align_assertion_2b_t));
|
||||
assert(sizeof(align_assertion_1a_t) == 3*9);
|
||||
assert(sizeof(align_assertion_2a_t) == 3*17);
|
||||
COMPILE_TIME_ASSERT(sizeof(align_assertion_1a_t) == sizeof(align_assertion_1b_t));
|
||||
COMPILE_TIME_ASSERT(sizeof(align_assertion_2a_t) == sizeof(align_assertion_2b_t));
|
||||
COMPILE_TIME_ASSERT(sizeof(align_assertion_1a_t) == 3*9);
|
||||
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;
|
||||
static char default_argv0[] = "upx";
|
||||
int cmdline_cmd = CMD_NONE;
|
||||
// int cmdline_cmd = CMD_NONE;
|
||||
|
||||
upx_sanity_check();
|
||||
init_options(opt);
|
||||
|
||||
#if defined(WITH_MSS)
|
||||
MSS_DISABLE_LOG_OUTPUT;
|
||||
#if 0 && defined(__DJGPP__)
|
||||
// LFN=n may cause problems with 2.03's _rename and mkdir under WinME
|
||||
putenv("LFN=y");
|
||||
#endif
|
||||
|
||||
#if defined(__EMX__)
|
||||
_response(&argc,&argv);
|
||||
_wildcard(&argc,&argv);
|
||||
#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])
|
||||
argv[0] = default_argv0;
|
||||
@@ -1011,15 +1133,15 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
char *prog = fn_basename(argv0);
|
||||
char *p;
|
||||
bool allupper = 1;
|
||||
bool allupper = true;
|
||||
for (p = prog; *p; p++)
|
||||
if (islower((unsigned char)*p))
|
||||
allupper = 0;
|
||||
allupper = false;
|
||||
if (allupper)
|
||||
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)
|
||||
*p = 0;
|
||||
}
|
||||
@@ -1043,7 +1165,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
#endif
|
||||
#if defined(WITH_NRV)
|
||||
if (nrv_init() != NRV_E_OK)
|
||||
if (nrv_init() != NRV_E_OK || NRV_VERSION != nrv_version())
|
||||
{
|
||||
show_head();
|
||||
fprintf(stderr,"nrv_init() failed - check your NRV installation !\n");
|
||||
@@ -1067,7 +1189,7 @@ int main(int argc, char *argv[])
|
||||
assert(i <= argc);
|
||||
|
||||
set_term(0);
|
||||
cmdline_cmd = opt->cmd;
|
||||
// cmdline_cmd = opt->cmd;
|
||||
switch (opt->cmd)
|
||||
{
|
||||
case CMD_NONE:
|
||||
@@ -1106,7 +1228,6 @@ int main(int argc, char *argv[])
|
||||
// invalidate compression options
|
||||
opt->method = 0;
|
||||
opt->level = 0;
|
||||
opt->mem_level = 0;
|
||||
memset(&opt->crp, 0xff, sizeof(opt->crp));
|
||||
}
|
||||
|
||||
@@ -1128,7 +1249,7 @@ int main(int argc, char *argv[])
|
||||
set_term(stdout);
|
||||
do_files(i,argc,argv);
|
||||
|
||||
#if 1 && (UPX_VERSION < 0x012000)
|
||||
#if 1 && (UPX_VERSION_HEX < 0x020000)
|
||||
{
|
||||
FILE *f = stdout;
|
||||
int fg = con_fg(f,FG_RED);
|
||||
@@ -1136,7 +1257,7 @@ int main(int argc, char *argv[])
|
||||
fg = con_fg(f,fg);
|
||||
}
|
||||
#endif
|
||||
#if 1 && !defined(WITH_NRV)
|
||||
#if 0 && !defined(WITH_NRV)
|
||||
{
|
||||
FILE *f = stdout;
|
||||
int fg = con_fg(f,FG_GREEN);
|
||||
|
||||
+11
-21
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
@@ -44,11 +44,10 @@ MemBuffer::MemBuffer(unsigned size) :
|
||||
|
||||
MemBuffer::~MemBuffer()
|
||||
{
|
||||
this->free();
|
||||
this->dealloc();
|
||||
}
|
||||
|
||||
|
||||
void MemBuffer::free()
|
||||
void MemBuffer::dealloc()
|
||||
{
|
||||
if (alloc_ptr)
|
||||
::free(alloc_ptr);
|
||||
@@ -69,17 +68,14 @@ unsigned MemBuffer::getSize() const
|
||||
|
||||
void MemBuffer::alloc(unsigned size, unsigned base_offset)
|
||||
{
|
||||
#if 0
|
||||
this->free();
|
||||
#else
|
||||
// don't automaticlly free a used buffer
|
||||
#endif
|
||||
// NOTE: we don't automaticlly free a used buffer
|
||||
assert(alloc_ptr == NULL);
|
||||
assert((int)size > 0);
|
||||
size = base_offset + size;
|
||||
alloc_ptr = (unsigned char *) malloc(size);
|
||||
if (!alloc_ptr)
|
||||
{
|
||||
//throw bad_alloc();
|
||||
throwCantPack("out of memory");
|
||||
//exit(1);
|
||||
}
|
||||
@@ -96,20 +92,14 @@ void MemBuffer::alloc(unsigned size)
|
||||
|
||||
void MemBuffer::allocForCompression(unsigned uncompressed_size)
|
||||
{
|
||||
// Idea:
|
||||
// We allocate the buffer at an offset of 4096 so
|
||||
// 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);
|
||||
assert((int)uncompressed_size > 0);
|
||||
alloc(uncompressed_size + uncompressed_size/8 + 256, 0);
|
||||
}
|
||||
|
||||
|
||||
void MemBuffer::allocForUncompression(unsigned uncompressed_size)
|
||||
{
|
||||
assert((int)uncompressed_size > 0);
|
||||
//alloc(uncompressed_size + 3 + 512, 0); // 512 safety bytes
|
||||
alloc(uncompressed_size + 3, 0); // 3 bytes for asm_fast decompresion
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
@@ -44,19 +44,21 @@ public:
|
||||
void allocForCompression(unsigned uncompressed_size);
|
||||
void allocForUncompression(unsigned uncompressed_size);
|
||||
|
||||
void free();
|
||||
void dealloc();
|
||||
|
||||
const unsigned char *getBuf() const { return ptr; }
|
||||
unsigned getSize() const ;
|
||||
unsigned getSize() const;
|
||||
|
||||
operator unsigned char * () { 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:
|
||||
void alloc(unsigned size, unsigned base_offset);
|
||||
|
||||
protected:
|
||||
unsigned char *ptr;
|
||||
unsigned char *alloc_ptr;
|
||||
unsigned alloc_size;
|
||||
@@ -67,13 +69,16 @@ private:
|
||||
MemBuffer& operator= (MemBuffer const &); // { return *this; }
|
||||
|
||||
// disable dynamic allocation
|
||||
#ifndef new
|
||||
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 *) {}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#endif /* already included */
|
||||
|
||||
|
||||
|
||||
+5
-6
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<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)
|
||||
{
|
||||
set_ec(EXIT_ERROR);
|
||||
fflush(stdout); fflush(stderr);
|
||||
char buf[1024];
|
||||
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)
|
||||
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
|
||||
*/
|
||||
|
||||
+43
-47
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
@@ -35,8 +35,6 @@
|
||||
static const
|
||||
#include "stub/l_com.h"
|
||||
|
||||
#define STACKSIZE 0x60
|
||||
|
||||
//#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))
|
||||
return M_NRV2B_LE16;
|
||||
static const int m_nrv2b[] = { M_NRV2B_LE16, -1 };
|
||||
if (M_IS_NRV2B(method))
|
||||
return m_nrv2b;
|
||||
#if 0
|
||||
// NOT IMPLEMENTED
|
||||
if (M_IS_NRV2D(opt->method))
|
||||
return M_NRV2D_LE16;
|
||||
static const int m_nrv2d[] = { M_NRV2D_LE16, -1 };
|
||||
if (M_IS_NRV2D(method))
|
||||
return m_nrv2d;
|
||||
#endif
|
||||
return M_NRV2B_LE16;
|
||||
UNUSED(level);
|
||||
return m_nrv2b;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -72,14 +75,13 @@ bool PackCom::canPack()
|
||||
{
|
||||
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
|
||||
|| memcmp (buf,"\xff\xff\xff\xff",4) == 0) // .sys
|
||||
return false;
|
||||
if (!fn_has_ext(fi->getName(),"com"))
|
||||
return false;
|
||||
if (find_le32(buf,128,UPX_MAGIC_LE32) >= 0)
|
||||
throwAlreadyPacked();
|
||||
checkAlreadyPacked(buf, sizeof(buf));
|
||||
if (file_size < 1024)
|
||||
throwCantPack("file is too small");
|
||||
if (file_size > 0xFF00)
|
||||
@@ -94,17 +96,20 @@ bool PackCom::canPack()
|
||||
|
||||
void PackCom::patchLoader(OutputFile *fo,
|
||||
upx_byte *loader, int lsize,
|
||||
unsigned calls, unsigned overlapoh)
|
||||
unsigned calls)
|
||||
{
|
||||
const int filter_id = ph.filter;
|
||||
const int e_len = getLoaderSection("COMCUTPO");
|
||||
const int e_len = getLoaderSectionStart("COMCUTPO");
|
||||
const int d_len = lsize - e_len;
|
||||
assert(e_len > 0 && e_len < 256);
|
||||
assert(d_len > 0 && d_len < 256);
|
||||
|
||||
const unsigned upper_end = ph.u_len + overlapoh + d_len + 0x100;
|
||||
if (upper_end + STACKSIZE > 0xfffe)
|
||||
throwNotCompressible();
|
||||
const unsigned upper_end = ph.u_len + ph.overlap_overhead + d_len + 0x100;
|
||||
unsigned stacksize = 0x60;
|
||||
if (upper_end + stacksize > 0xfffe)
|
||||
stacksize = 0x56;
|
||||
if (upper_end + stacksize > 0xfffe)
|
||||
throwCantPack("file is too big for dos/com");
|
||||
|
||||
if (filter_id)
|
||||
{
|
||||
@@ -116,11 +121,11 @@ void PackCom::patchLoader(OutputFile *fo,
|
||||
|
||||
// NOTE: Depends on: decompr_start == cutpoint+1 !!!
|
||||
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,"SI",ph.c_len + lsize + 0x100);
|
||||
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
|
||||
fo->write(loader,e_len); // entry
|
||||
@@ -136,19 +141,23 @@ void PackCom::patchLoader(OutputFile *fo,
|
||||
|
||||
int PackCom::buildLoader(const Filter *ft)
|
||||
{
|
||||
const int filter_id = ft->id;
|
||||
initLoader(nrv2b_loader,sizeof(nrv2b_loader));
|
||||
addLoader("COMMAIN1""COMSUBSI",
|
||||
filter_id ? "COMCALLT" : "",
|
||||
ph.first_offset_found == 1 ? "COMSBBBP" : "",
|
||||
"COMPSHDI",
|
||||
ft->id ? "COMCALLT" : "",
|
||||
"COMMAIN2""UPX1HEAD""COMCUTPO""NRV2B160",
|
||||
filter_id ? "NRVDDONE" : "NRVDRETU",
|
||||
ft->id ? "NRVDDONE" : "NRVDRETU",
|
||||
"NRVDECO1",
|
||||
ph.max_offset_found <= 0xd00 ? "NRVLED00" : "NRVGTD00",
|
||||
"NRVDECO2""NRV2B169",
|
||||
NULL
|
||||
);
|
||||
if (filter_id)
|
||||
addFilter16(filter_id);
|
||||
if (ft->id)
|
||||
{
|
||||
assert(ft->calls > 0);
|
||||
addFilter16(ft->id);
|
||||
}
|
||||
return getLoaderSize();
|
||||
}
|
||||
|
||||
@@ -192,35 +201,22 @@ void PackCom::pack(OutputFile *fo)
|
||||
|
||||
// prepare packheader
|
||||
ph.u_len = file_size;
|
||||
ph.filter = 0;
|
||||
// prepare filter
|
||||
Filter ft(opt->level);
|
||||
Filter ft(ph.level);
|
||||
ft.addvalue = getCallTrickOffset();
|
||||
// prepare other settings
|
||||
// compress
|
||||
const unsigned overlap_range = ph.u_len < 0xFE00 - ft.addvalue ? 32 : 0;
|
||||
unsigned overlapoh;
|
||||
|
||||
int strategy = -1; // try the first working filter
|
||||
if (opt->filter >= 0 && isValidFilter(opt->filter))
|
||||
// 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);
|
||||
compressWithFilters(&ft, overlap_range);
|
||||
|
||||
const int lsize = getLoaderSize();
|
||||
MemBuffer loader(lsize);
|
||||
memcpy(loader,getLoader(),lsize);
|
||||
|
||||
const unsigned calls = ft.id % 3 ? ft.lastcall - 2 * ft.calls : ft.calls;
|
||||
patchLoader(fo, loader, lsize, calls, overlapoh);
|
||||
patchLoader(fo, loader, lsize, calls);
|
||||
|
||||
// verify
|
||||
verifyOverlappingDecompression(&obuf, overlapoh);
|
||||
verifyOverlappingDecompression();
|
||||
|
||||
// finally check the compression ratio
|
||||
if (!checkFinalCompressionRatio(fo))
|
||||
@@ -234,7 +230,7 @@ void PackCom::pack(OutputFile *fo)
|
||||
|
||||
int PackCom::canUnpack()
|
||||
{
|
||||
if (!readPackHeader(128, 0))
|
||||
if (!readPackHeader(128))
|
||||
return false;
|
||||
if (file_size <= (off_t) ph.c_len)
|
||||
return false;
|
||||
|
||||
+7
-7
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
@@ -39,10 +39,10 @@ class PackCom : public Packer
|
||||
typedef Packer super;
|
||||
public:
|
||||
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 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 void pack(OutputFile *fo);
|
||||
@@ -56,7 +56,7 @@ protected:
|
||||
|
||||
protected:
|
||||
virtual int buildLoader(const Filter *ft);
|
||||
virtual void patchLoader(OutputFile *fo, upx_byte *, int, unsigned, unsigned);
|
||||
virtual void patchLoader(OutputFile *fo, upx_byte *, int, unsigned);
|
||||
virtual void addFilter16(int filter_id);
|
||||
};
|
||||
|
||||
|
||||
+63
-77
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,10 +21,11 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
#include "file.h"
|
||||
#include "filter.h"
|
||||
@@ -45,28 +46,41 @@ static const
|
||||
PackDjgpp2::PackDjgpp2(InputFile *f) :
|
||||
super(f), coff_offset(0)
|
||||
{
|
||||
assert(sizeof(coff_hdr) == 0xa8);
|
||||
assert(sizeof(stubify_stub) == 2048);
|
||||
COMPILE_TIME_ASSERT(sizeof(external_scnhdr_t) == 40);
|
||||
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 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;
|
||||
return Packer::getDefaultCompressionMethods_le32(method, level);
|
||||
}
|
||||
|
||||
|
||||
const int *PackDjgpp2::getFilters() const
|
||||
{
|
||||
static const int filters[] = { 0x26, 0x24, 0x11, 0x14, 0x13, 0x16,
|
||||
0x25, 0x15, 0x12, -1 };
|
||||
static const int filters[] = {
|
||||
0x26, 0x24, 0x11, 0x14, 0x13, 0x16, 0x25, 0x15, 0x12,
|
||||
-1 };
|
||||
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)
|
||||
{
|
||||
// prepare loader
|
||||
@@ -127,7 +141,7 @@ static bool is_dlm(InputFile *fi, long coff_offset)
|
||||
fi->readx(buf,4);
|
||||
if (memcmp(buf,"DLMF",4) == 0)
|
||||
return true;
|
||||
} catch (IOException&) {
|
||||
} catch (const IOException&) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -136,29 +150,31 @@ static bool is_dlm(InputFile *fi, long coff_offset)
|
||||
static void handle_allegropak(InputFile *fi, OutputFile *fo)
|
||||
{
|
||||
unsigned char buf[0x4000];
|
||||
unsigned pfsize=0, ic;
|
||||
int pfsize = 0;
|
||||
|
||||
try {
|
||||
fi->seek(-8,SEEK_END);
|
||||
fi->readx(buf,8);
|
||||
if (memcmp(buf,"slh+",4) != 0)
|
||||
fi->seek(-8, SEEK_END);
|
||||
fi->readx(buf, 8);
|
||||
if (memcmp(buf, "slh+", 4) != 0)
|
||||
return;
|
||||
pfsize = get_be32(buf+4);
|
||||
fi->seek(-(off_t)pfsize,SEEK_END);
|
||||
} catch (IOException&) {
|
||||
pfsize = get_be32_signed(buf+4);
|
||||
if (pfsize <= 8 || pfsize >= fi->st.st_size)
|
||||
return;
|
||||
fi->seek(-pfsize, SEEK_END);
|
||||
} catch (const IOException&) {
|
||||
return;
|
||||
}
|
||||
while (pfsize)
|
||||
while (pfsize > 0)
|
||||
{
|
||||
ic = pfsize < sizeof(buf) ? pfsize : sizeof(buf);
|
||||
fi->readx(buf,ic);
|
||||
fo->write(buf,ic);
|
||||
pfsize -= ic;
|
||||
const int len = UPX_MIN(pfsize, (int)sizeof(buf));
|
||||
fi->readx(buf, len);
|
||||
fo->write(buf, len);
|
||||
pfsize -= len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool PackDjgpp2::readFileHeader()
|
||||
int PackDjgpp2::readFileHeader()
|
||||
{
|
||||
unsigned char hdr[0x1c];
|
||||
unsigned char magic[8];
|
||||
@@ -173,7 +189,7 @@ bool PackDjgpp2::readFileHeader()
|
||||
fi->seek(512,SEEK_SET);
|
||||
fi->readx(magic,8);
|
||||
if (memcmp("go32stub",magic,8) != 0)
|
||||
return false; // not V2 image
|
||||
return 0; // not V2 image
|
||||
fi->seek(coff_offset,SEEK_SET);
|
||||
if (fi->read(&coff_hdr,sizeof(coff_hdr)) != sizeof(coff_hdr))
|
||||
throwCantPack("skipping djgpp symlink");
|
||||
@@ -184,17 +200,17 @@ bool PackDjgpp2::readFileHeader()
|
||||
fi->readx(&coff_hdr,0xa8);
|
||||
}
|
||||
if (coff_hdr.f_magic != 0x014c) // I386MAGIC
|
||||
return false;
|
||||
return 0;
|
||||
if ((coff_hdr.f_flags & 2) == 0) // F_EXEC - COFF executable
|
||||
return false;
|
||||
return 0;
|
||||
if (coff_hdr.a_magic != 0413) // ZMAGIC - demand load format
|
||||
return false;
|
||||
return 0;
|
||||
// FIXME: check for Linux etc.
|
||||
|
||||
text = coff_hdr.sh;
|
||||
data = text + 1;
|
||||
bss = data + 1;
|
||||
return true;
|
||||
return UPX_F_DJGPP2_COFF;
|
||||
}
|
||||
|
||||
|
||||
@@ -257,6 +273,8 @@ void PackDjgpp2::pack(OutputFile *fo)
|
||||
const unsigned hdrsize = 20 + 28 + (40 * coff_hdr.f_nscns);
|
||||
if (hdrsize < sizeof(coff_hdr) || hdrsize > tpos)
|
||||
throwCantPack("coff header error");
|
||||
if (hdrsize > (tpos & 0x1ff))
|
||||
throwCantPack("unsupported coff header");
|
||||
|
||||
ibuf.alloc(usize);
|
||||
obuf.allocForCompression(usize);
|
||||
@@ -267,59 +285,26 @@ void PackDjgpp2::pack(OutputFile *fo)
|
||||
fi->seek(coff_offset+tpos,SEEK_SET);
|
||||
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
|
||||
ph.u_len = usize;
|
||||
ph.filter = 0;
|
||||
// prepare filter
|
||||
Filter ft(opt->level);
|
||||
Filter ft(ph.level);
|
||||
ft.buf_len = usize - data->size;
|
||||
ft.addvalue = text->vaddr & ~0x1ff;
|
||||
// prepare other settings
|
||||
const unsigned overlap_range = 512;
|
||||
unsigned overlapoh;
|
||||
|
||||
int strategy = -1; // try the first working filter
|
||||
if (opt->filter >= 0 && isValidFilter(opt->filter))
|
||||
// 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
|
||||
// compress
|
||||
compressWithFilters(&ft, 512);
|
||||
|
||||
// patch coff header #2
|
||||
const unsigned lsize = getLoaderSize();
|
||||
text->size = lsize; // new size of .text
|
||||
data->size = ph.c_len; // new size of .data
|
||||
|
||||
if (bss->size < overlapoh) // give it a .bss
|
||||
bss->size = overlapoh;
|
||||
if (bss->size < ph.overlap_overhead) // give it a .bss
|
||||
bss->size = ph.overlap_overhead;
|
||||
|
||||
text->scnptr = sizeof(coff_hdr);
|
||||
data->scnptr = text->scnptr + text->size;
|
||||
data->vaddr = bss->vaddr + ((data->scnptr + data->size) & 0x1ff) - data->size + overlapoh - 0x200;
|
||||
data->vaddr = bss->vaddr + ((data->scnptr + data->size) & 0x1ff) - data->size + ph.overlap_overhead - 0x200;
|
||||
coff_hdr.f_nscns = 3;
|
||||
|
||||
// prepare loader
|
||||
@@ -330,7 +315,7 @@ void PackDjgpp2::pack(OutputFile *fo)
|
||||
patchPackHeader(loader,lsize);
|
||||
patch_le32(loader,lsize,"ENTR",coff_hdr.a_entry);
|
||||
patchFilter32(loader, lsize, &ft);
|
||||
patch_le32(loader,lsize,"BSSL",overlapoh/4);
|
||||
patch_le32(loader,lsize,"BSSL",ph.overlap_overhead/4);
|
||||
assert(bss->vaddr == ((size + 0x1ff) &~ 0x1ff) + (text->vaddr &~ 0x1ff));
|
||||
patch_le32(loader,lsize,"OUTP",text->vaddr &~ 0x1ff);
|
||||
patch_le32(loader,lsize,"INPP",data->vaddr);
|
||||
@@ -338,8 +323,8 @@ void PackDjgpp2::pack(OutputFile *fo)
|
||||
// patch coff header #3
|
||||
text->vaddr = sizeof(coff_hdr);
|
||||
coff_hdr.a_entry = sizeof(coff_hdr) + getLoaderSection("DJ2MAIN1");
|
||||
bss->vaddr += overlapoh;
|
||||
bss->size -= overlapoh;
|
||||
bss->vaddr += ph.overlap_overhead;
|
||||
bss->size -= ph.overlap_overhead;
|
||||
|
||||
// because of a feature (bug?) in stub.asm we need some padding
|
||||
memcpy(obuf+data->size,"UPX",3);
|
||||
@@ -356,7 +341,7 @@ void PackDjgpp2::pack(OutputFile *fo)
|
||||
#endif
|
||||
|
||||
// verify
|
||||
verifyOverlappingDecompression(&obuf, overlapoh);
|
||||
verifyOverlappingDecompression();
|
||||
|
||||
// handle overlay
|
||||
// FIXME: only Allegro pakfiles are supported
|
||||
@@ -378,7 +363,8 @@ int PackDjgpp2::canUnpack()
|
||||
return false;
|
||||
if (is_dlm(fi,coff_offset))
|
||||
throwCantUnpack("can't handle DLM");
|
||||
return readPackHeader(1024, coff_offset) ? 1 : -1;
|
||||
fi->seek(coff_offset, SEEK_SET);
|
||||
return readPackHeader(1024) ? 1 : -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+17
-10
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
@@ -40,10 +40,10 @@ class PackDjgpp2 : public Packer
|
||||
|
||||
public:
|
||||
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 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 void pack(OutputFile *fo);
|
||||
@@ -53,8 +53,13 @@ public:
|
||||
virtual int canUnpack();
|
||||
|
||||
protected:
|
||||
virtual int buildLoader(const Filter *ft);
|
||||
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;
|
||||
|
||||
@@ -66,7 +71,8 @@ protected:
|
||||
LE32 scnptr;
|
||||
char misc[12]; // relptr, lnnoptr, nreloc, nlnno
|
||||
char __[4]; // flags
|
||||
};
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
struct coff_header_t
|
||||
{
|
||||
@@ -90,11 +96,12 @@ protected:
|
||||
|
||||
// section headers
|
||||
external_scnhdr_t sh[3];
|
||||
} coff_hdr;
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
coff_header_t coff_hdr;
|
||||
external_scnhdr_t *text,*data,*bss;
|
||||
|
||||
bool readFileHeader();
|
||||
void stripDebug();
|
||||
};
|
||||
|
||||
|
||||
+33
-12
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
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_shnum; /* Section header table entry count */
|
||||
LE16 e_shstrndx; /* Section header string table index */
|
||||
};
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
|
||||
// Program segment header.
|
||||
@@ -65,19 +66,39 @@ struct Elf_LE32_Phdr
|
||||
LE32 p_memsz; /* Segment size in memory */
|
||||
LE32 p_flags; /* Segment flags */
|
||||
LE32 p_align; /* Segment alignment */
|
||||
};
|
||||
|
||||
// Values for p_type
|
||||
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
|
||||
enum { PF_X = (1 << 0) }; /* Segment is executable */
|
||||
enum { PF_W = (1 << 1) }; /* Segment is writable */
|
||||
enum { PF_R = (1 << 2) }; /* Segment is readable */
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
|
||||
// Values for p_type
|
||||
#define PT_LOAD 1 /* Loadable program segment */
|
||||
struct Elf_LE32_Dyn
|
||||
{
|
||||
LE32 d_tag;
|
||||
LE32 d_val;
|
||||
|
||||
// Values for p_flags
|
||||
#define PF_X (1 << 0) /* Segment is executable */
|
||||
#define PF_W (1 << 1) /* Segment is writable */
|
||||
#define PF_R (1 << 2) /* Segment is readable */
|
||||
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 */
|
||||
|
||||
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
|
||||
+193
-157
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
@@ -39,6 +39,8 @@ static const
|
||||
#define MAXMATCH 0x2000
|
||||
#define MAXRELOCS (0x8000-MAXMATCH)
|
||||
|
||||
#define DI_LIMIT 0xff00 // see the assembly why
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
@@ -47,18 +49,15 @@ static const
|
||||
PackExe::PackExe(InputFile *f) :
|
||||
super(f)
|
||||
{
|
||||
assert(sizeof(exe_header_t) == 32);
|
||||
COMPILE_TIME_ASSERT(sizeof(exe_header_t) == 32);
|
||||
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))
|
||||
return M_NRV2B_8;
|
||||
if (M_IS_NRV2D(opt->method))
|
||||
return M_NRV2D_8;
|
||||
return opt->level > 1 && ih_imagesize >= 300000 ? M_NRV2D_8 : M_NRV2B_8;
|
||||
bool small = ih_imagesize <= 256*1024;
|
||||
return Packer::getDefaultCompressionMethods_8(method, level, small);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
fi->readx(&ih,sizeof(ih));
|
||||
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_imagesize = ih_exesize - ih.headsize16*16;
|
||||
ih_overlay = file_size - ih_exesize;
|
||||
@@ -88,7 +196,7 @@ bool PackExe::readFileHeader()
|
||||
#if 0
|
||||
printf("dos/exe header: %d %d %d\n", ih_exesize, ih_imagesize, ih_overlay);
|
||||
#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,
|
||||
upx_byte *crel, bool *has_9a)
|
||||
{
|
||||
upx_byte *crel_save = crel;
|
||||
upx_byte * const crel_save = crel;
|
||||
unsigned i;
|
||||
unsigned seg_high = 0;
|
||||
#if 0
|
||||
@@ -241,35 +349,25 @@ unsigned optimize_relocs(upx_byte *b, const unsigned size,
|
||||
void PackExe::pack(OutputFile *fo)
|
||||
{
|
||||
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)
|
||||
throwCantPack("too many relocations");
|
||||
checkOverlay(overlay);
|
||||
checkOverlay(ih_overlay);
|
||||
|
||||
// alloc buffers
|
||||
unsigned relocsize = RSFCRI + 4*ih.relocs;
|
||||
|
||||
ibuf.alloc(imagesize+16+relocsize+2);
|
||||
obuf.allocForCompression(imagesize+16+relocsize+2);
|
||||
relocsize = RSFCRI + 4*ih.relocs;
|
||||
ibuf.alloc(ih_imagesize+16+relocsize+2);
|
||||
obuf.allocForCompression(ih_imagesize+16+relocsize+2);
|
||||
|
||||
// read image
|
||||
fi->seek(ih.headsize16*16,SEEK_SET);
|
||||
fi->readx(ibuf,imagesize);
|
||||
fi->readx(ibuf,ih_imagesize);
|
||||
|
||||
if (find_le32(ibuf, UPX_MAX(imagesize, 127u), UPX_MAGIC_LE32) >= 0)
|
||||
throwAlreadyPacked();
|
||||
checkAlreadyPacked(ibuf, UPX_MIN(ih_imagesize, 127u));
|
||||
|
||||
// relocations
|
||||
has_9a = false;
|
||||
upx_byte *w = ibuf + imagesize;
|
||||
upx_byte *w = ibuf + ih_imagesize;
|
||||
if (ih.relocs)
|
||||
{
|
||||
upx_byte *wr = w + RSFCRI;
|
||||
@@ -283,7 +381,7 @@ void PackExe::pack(OutputFile *fo)
|
||||
set_le32(wr+4*ic, (jc>>16)*16+(jc&0xffff));
|
||||
}
|
||||
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);
|
||||
relocsize += 2;
|
||||
if (relocsize > MAXRELOCS)
|
||||
@@ -298,139 +396,68 @@ void PackExe::pack(OutputFile *fo)
|
||||
}
|
||||
else
|
||||
{
|
||||
flag |= NORELOC;
|
||||
relocsize = 0;
|
||||
}
|
||||
|
||||
ph.u_len = imagesize + relocsize;
|
||||
if (!compress(ibuf,obuf,0,MAXMATCH))
|
||||
throwNotCompressible();
|
||||
const unsigned overlapoh = findOverlapOverhead(obuf,32);
|
||||
|
||||
// prepare packheader
|
||||
ph.u_len = ih_imagesize + relocsize;
|
||||
// prepare filter
|
||||
Filter ft(ph.level);
|
||||
// compress
|
||||
compressWithFilters(&ft, 32, 0, NULL, 0, MAXMATCH);
|
||||
if (ph.max_run_found + ph.max_match_found > 0x8000)
|
||||
throwCantPack("decompressor limit exceeded, send a bugreport");
|
||||
|
||||
#ifdef TESTING
|
||||
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",
|
||||
0/*ph.min_offset_found*/,ph.max_offset_found,
|
||||
0/*ph.min_match_found*/,ph.max_match_found,
|
||||
0/*ph.min_run_found*/,ph.max_run_found);
|
||||
}
|
||||
#endif
|
||||
const unsigned packedsize = ph.c_len;
|
||||
|
||||
if (!opt->dos.no_reloc)
|
||||
flag |= USEJUMP;
|
||||
int flag = fillExeHeader(&oh);
|
||||
|
||||
// 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();
|
||||
MemBuffer loader(lsize);
|
||||
memcpy(loader,getLoader(),lsize);
|
||||
//OutputFile::dump("xxloader.dat", loader, lsize);
|
||||
|
||||
// patch loader
|
||||
const unsigned e_len = getLoaderSection("EXECUTPO");
|
||||
const unsigned packedsize = ph.c_len;
|
||||
const unsigned e_len = getLoaderSectionStart("EXECUTPO");
|
||||
const unsigned d_len = lsize - e_len;
|
||||
assert((e_len&15) == 0);
|
||||
|
||||
const unsigned copysize = (1+packedsize+d_len) & ~1;
|
||||
const unsigned firstcopy = copysize%0x10000 ? copysize%0x10000 : 0x10000;
|
||||
|
||||
oh.headsize16 = 2;
|
||||
oh.ip = 0;
|
||||
|
||||
ic = ih.min*16+imagesize;
|
||||
if (ic < oh.ss*16u + oh.sp)
|
||||
ic = oh.ss*16u + oh.sp;
|
||||
|
||||
// set oh.min & oh.max
|
||||
ic = ih.min*16 + ih_imagesize;
|
||||
if (ic < oh.ss*16 + oh.sp)
|
||||
ic = oh.ss*16 + oh.sp;
|
||||
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;
|
||||
|
||||
// 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)
|
||||
{
|
||||
set_le16(extra_info+eisize,ih.min);
|
||||
@@ -443,7 +470,9 @@ void PackExe::pack(OutputFile *fo)
|
||||
eisize += 2;
|
||||
flag |= MAXMEM;
|
||||
}
|
||||
extra_info[eisize++] = (unsigned char) flag;
|
||||
|
||||
// patch loader
|
||||
if (flag & USEJUMP)
|
||||
{
|
||||
// I use a relocation entry to set the original cs
|
||||
@@ -461,7 +490,10 @@ void PackExe::pack(OutputFile *fo)
|
||||
oh.relocs = 0;
|
||||
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)
|
||||
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,"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,"DS",e_len/16+(copysize-firstcopy)/16);
|
||||
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))
|
||||
// throwCantPack("FIXME");
|
||||
|
||||
extra_info[eisize++] = flag;
|
||||
const unsigned outputlen = sizeof(oh)+lsize+packedsize+eisize;
|
||||
oh.m512 = outputlen & 511;
|
||||
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
|
||||
#ifdef TESTING
|
||||
@@ -511,10 +543,10 @@ void PackExe::pack(OutputFile *fo)
|
||||
#endif
|
||||
|
||||
// verify
|
||||
verifyOverlappingDecompression(&obuf, overlapoh);
|
||||
verifyOverlappingDecompression();
|
||||
|
||||
// copy the overlay
|
||||
copyOverlay(fo, overlay, &obuf);
|
||||
copyOverlay(fo, ih_overlay, &obuf);
|
||||
//fprintf (stderr,"%x %x\n",relocsize,ph.u_len);
|
||||
|
||||
// finally check the compression ratio
|
||||
@@ -531,8 +563,9 @@ int PackExe::canUnpack()
|
||||
{
|
||||
if (!readFileHeader())
|
||||
return false;
|
||||
const off_t off = ih.headsize16*16;
|
||||
bool b = readPackHeader(128, off);
|
||||
const off_t off = ih.headsize16 * 16;
|
||||
fi->seek(off, SEEK_SET);
|
||||
bool b = readPackHeader(128);
|
||||
return b && (off + (off_t) ph.c_len <= file_size);
|
||||
}
|
||||
|
||||
@@ -547,23 +580,22 @@ void PackExe::unpack(OutputFile *fo)
|
||||
obuf.allocForUncompression(ph.u_len);
|
||||
|
||||
// read the file
|
||||
unsigned imagesize = ih_imagesize;
|
||||
const unsigned overlay = ih_overlay;
|
||||
|
||||
fi->seek(ih.headsize16*16,SEEK_SET);
|
||||
fi->readx(ibuf,imagesize);
|
||||
fi->readx(ibuf,ih_imagesize);
|
||||
|
||||
// get compressed data offset
|
||||
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");
|
||||
|
||||
checkOverlay(overlay);
|
||||
checkOverlay(ih_overlay);
|
||||
|
||||
// decompress
|
||||
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;
|
||||
upx_byte *relocs = obuf + ph.u_len;
|
||||
@@ -613,20 +645,23 @@ void PackExe::unpack(OutputFile *fo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fill new exe header
|
||||
memset(&oh,0,sizeof(oh));
|
||||
oh.ident = 'M' + 'Z'*256;
|
||||
|
||||
oh.relocs = relocn;
|
||||
while (relocn&3)
|
||||
set_le32(wrkmem+4*relocn++,0);
|
||||
if (relocn)
|
||||
{
|
||||
oh.relocs = relocn;
|
||||
while (relocn & 3)
|
||||
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.p512 = (outputlen + 511) >> 9;
|
||||
oh.headsize16 = 2+relocn/4;
|
||||
|
||||
imagesize--;
|
||||
oh.max = ih.max;
|
||||
oh.min = ih.min;
|
||||
oh.sp = ih.sp;
|
||||
@@ -652,11 +687,12 @@ void PackExe::unpack(OutputFile *fo)
|
||||
|
||||
// write header + relocations + uncompressed file
|
||||
fo->write(&oh,sizeof(oh));
|
||||
fo->write(wrkmem,relocn*4);
|
||||
fo->write(obuf,relocs-obuf);
|
||||
if (relocn)
|
||||
fo->write(wrkmem,relocn*4);
|
||||
fo->write(obuf, ptr_diff(relocs, obuf));
|
||||
|
||||
// copy the overlay
|
||||
copyOverlay(fo, overlay, &obuf);
|
||||
copyOverlay(fo, ih_overlay, &obuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+17
-8
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
@@ -39,10 +39,10 @@ class PackExe : public Packer
|
||||
typedef Packer super;
|
||||
public:
|
||||
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 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 void pack(OutputFile *fo);
|
||||
@@ -63,7 +63,12 @@ public:
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
@@ -82,11 +87,15 @@ protected:
|
||||
LE16 relocoffs;
|
||||
char __[2]; // overlnum
|
||||
LE32 firstreloc;
|
||||
} ih, oh;
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
exe_header_t ih, oh;
|
||||
|
||||
unsigned ih_exesize;
|
||||
unsigned ih_imagesize;
|
||||
unsigned ih_overlay;
|
||||
unsigned relocsize;
|
||||
|
||||
bool has_9a;
|
||||
|
||||
|
||||
+263
-250
@@ -2,9 +2,9 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
Copyright (C) 2000 John F. Reiser
|
||||
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
|
||||
@@ -22,275 +22,251 @@
|
||||
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
|
||||
|
||||
John F. Reiser
|
||||
jreiser@BitWagon.com
|
||||
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"
|
||||
#include "p_lx_elf.h"
|
||||
|
||||
#define PT_LOAD Elf_LE32_Phdr::PT_LOAD
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
static const
|
||||
#include "stub/l_le_n2b.h"
|
||||
#include "stub/l_lx_elf86.h"
|
||||
static const
|
||||
#include "stub/l_le_n2d.h"
|
||||
#include "stub/fold_elf86.h"
|
||||
|
||||
|
||||
PackLinuxI386elf::PackLinuxI386elf(InputFile *f) :
|
||||
super(f), phdri(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
PackLinuxI386elf::~PackLinuxI386elf()
|
||||
{
|
||||
delete phdri;
|
||||
delete[] phdri;
|
||||
}
|
||||
|
||||
PackLinuxI386elf::PackLinuxI386elf(InputFile *f)
|
||||
:super(f)
|
||||
,phdri(0)
|
||||
int const *
|
||||
PackLinuxI386elf::getFilters() const
|
||||
{
|
||||
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))
|
||||
return linux_i386elf_nrv2b_loader;
|
||||
if (M_IS_NRV2D(opt->method))
|
||||
return linux_i386elf_nrv2d_loader;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int PackLinuxI386elf::getLoaderSize() const
|
||||
{
|
||||
if (0 != lsize) {
|
||||
return lsize;
|
||||
unsigned char tmp[sizeof(linux_i386elf_fold)];
|
||||
memcpy(tmp, linux_i386elf_fold, sizeof(linux_i386elf_fold));
|
||||
checkPatch(NULL, 0, 0, 0); // reset
|
||||
if (opt->unix.ptinterp) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (M_IS_NRV2B(opt->method))
|
||||
return sizeof(linux_i386elf_nrv2b_loader);
|
||||
if (M_IS_NRV2D(opt->method))
|
||||
return sizeof(linux_i386elf_nrv2d_loader);
|
||||
return 0;
|
||||
return buildLinuxLoader(
|
||||
linux_i386elf_loader, sizeof(linux_i386elf_loader),
|
||||
tmp, sizeof(linux_i386elf_fold), ft );
|
||||
}
|
||||
|
||||
|
||||
static inline off_t min_off_t(off_t a, off_t b)
|
||||
{
|
||||
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();
|
||||
}
|
||||
void PackLinuxI386elf::patchLoader() { }
|
||||
|
||||
|
||||
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->seek(0,0);
|
||||
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_Phdr const *phdr = (Elf_LE32_Phdr const *)(ehdr->e_phoff +
|
||||
(char const *)ehdr);
|
||||
if (ehdr->e_phoff != sizeof(*ehdr)) {// Phdrs not contiguous with Ehdr
|
||||
return false;
|
||||
}
|
||||
// The first PT_LOAD must cover the beginning of the file (0==p_offset).
|
||||
for (unsigned j=0; j < ehdr->e_phnum; ++phdr, ++j) {
|
||||
if (PT_LOAD==phdr->p_type) {
|
||||
if (phdr->p_offset!=0) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
exetype = 1;
|
||||
return super::canPack();
|
||||
fi->readx(buf, sizeof(buf));
|
||||
fi->seek(0, SEEK_SET);
|
||||
Elf_LE32_Ehdr const *const ehdr = (Elf_LE32_Ehdr const *)buf;
|
||||
|
||||
// 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
|
||||
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).
|
||||
Elf_LE32_Phdr const *phdr = (Elf_LE32_Phdr const *)(buf + ehdr->e_phoff);
|
||||
for (unsigned j=0; j < ehdr->e_phnum; ++phdr, ++j) {
|
||||
if (j >= 14)
|
||||
return false;
|
||||
if (phdr->PT_LOAD == phdr->p_type) {
|
||||
if (phdr->p_offset != 0) {
|
||||
throwCantPack("invalid Phdr p_offset; try `--force-execve'");
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (!super::canPack())
|
||||
return false;
|
||||
assert(exetype == 1);
|
||||
|
||||
// set options
|
||||
opt->unix.blocksize = blocksize = file_size;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PackLinuxI386elf::packExtent(
|
||||
Extent const &x,
|
||||
OutputFile *fo,
|
||||
unsigned &total_in,
|
||||
unsigned &total_out
|
||||
unsigned &total_out,
|
||||
Filter *ft,
|
||||
OutputFile *fo
|
||||
)
|
||||
{
|
||||
fi->seek(x.offset, SEEK_SET);
|
||||
for (off_t rest = x.size; 0!=rest; )
|
||||
{
|
||||
int l = fi->readx(ibuf, min_off_t(rest, opt->unix.blocksize));
|
||||
if (l == 0)
|
||||
for (off_t rest = x.size; 0 != rest; ) {
|
||||
int const strategy = getStrategy(*ft);
|
||||
int l = fi->readx(ibuf, UPX_MIN(rest, (off_t)blocksize));
|
||||
if (l == 0) {
|
||||
break;
|
||||
}
|
||||
rest -= l;
|
||||
|
||||
// Note: compression for a block can fail if the
|
||||
// file is e.g. blocksize + 1 bytes long
|
||||
|
||||
// compress
|
||||
ph.u_len = l;
|
||||
compress(ibuf, obuf); // ignore return value
|
||||
|
||||
if (ph.c_len < ph.u_len)
|
||||
{
|
||||
if (!testOverlappingDecompression(obuf, OVERHEAD))
|
||||
throwNotCompressible();
|
||||
ph.c_len = ph.u_len = l;
|
||||
ph.overlap_overhead = 0;
|
||||
unsigned end_u_adler = 0;
|
||||
if (ft) {
|
||||
// compressWithFilters() updates u_adler _inside_ compress();
|
||||
// that is, AFTER filtering. We want BEFORE filtering,
|
||||
// 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;
|
||||
// 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
|
||||
unsigned char size[8];
|
||||
set_native32(size+0, ph.u_len);
|
||||
set_native32(size+4, ph.c_len);
|
||||
fo->write(size, 8);
|
||||
b_info tmp;
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
set_native32(&tmp.sz_unc, ph.u_len);
|
||||
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
|
||||
if (ph.c_len < ph.u_len)
|
||||
{
|
||||
if (ph.c_len < ph.u_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);
|
||||
}
|
||||
|
||||
if (ft) {
|
||||
ph.u_adler = end_u_adler;
|
||||
}
|
||||
total_in += ph.u_len;
|
||||
total_out += ph.c_len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PackLinuxI386elf::pack(OutputFile *fo)
|
||||
void PackLinuxI386elf::pack1(OutputFile *fo, Filter &)
|
||||
{
|
||||
// set options
|
||||
opt->unix.blocksize = blocksize = file_size;
|
||||
progid = 0; // not used
|
||||
|
||||
fi->seek(0, SEEK_SET);
|
||||
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];
|
||||
fi->seek(ehdri.e_phoff, SEEK_SET);
|
||||
fi->readx(phdri, sz_phdrs);
|
||||
|
||||
// prepare loader
|
||||
lsize = getLoaderSize();
|
||||
loader.alloc(lsize + sizeof(p_info));
|
||||
memcpy(loader,getLoader(),lsize);
|
||||
generateElfHdr(fo, linux_i386elf_fold, getbrk(phdri, ehdri.e_phnum) );
|
||||
}
|
||||
|
||||
// patch loader, prepare header info, write loader + header info
|
||||
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()
|
||||
void PackLinuxI386elf::pack2(OutputFile *fo, Filter &ft)
|
||||
{
|
||||
Extent x;
|
||||
unsigned k;
|
||||
|
||||
// count passes, set ptload vars
|
||||
ui_total_passes = 0;
|
||||
off_t ptload0hi = 0, ptload1lo = 0;
|
||||
int nx = 0;
|
||||
off_t ptload0hi = 0, ptload1lo = 0, ptload1sz = 0;
|
||||
for (k = 0; k < ehdri.e_phnum; ++k) {
|
||||
if (PT_LOAD == phdri[k].p_type) {
|
||||
x.offset = phdri[k].p_offset;
|
||||
@@ -300,84 +276,78 @@ void PackLinuxI386elf::pack(OutputFile *fo)
|
||||
}
|
||||
else if (0 == ptload1lo) {
|
||||
ptload1lo = x.offset;
|
||||
ptload1sz = x.size;
|
||||
}
|
||||
ui_total_passes++;
|
||||
} else {
|
||||
if (nx++ == 0)
|
||||
ui_total_passes++;
|
||||
}
|
||||
}
|
||||
if (ptload0hi < ptload1lo)
|
||||
if (0!=ptload1sz && ptload0hi < ptload1lo)
|
||||
ui_total_passes++;
|
||||
|
||||
// compress extents
|
||||
unsigned total_in = 0;
|
||||
unsigned total_out = 0;
|
||||
|
||||
ui_pass = -1; // Compressing Elf headers is invisible to UI.
|
||||
x.offset = 0;
|
||||
x.size = sizeof(Elf_LE32_Ehdr) + sz_phdrs;
|
||||
ui_pass = -1;
|
||||
packExtent(x, fo, total_in, total_out);
|
||||
ui_pass = 0;
|
||||
{
|
||||
int const old_level = ph.level; ph.level = 10;
|
||||
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) {
|
||||
if (ft.id < 0x40) {
|
||||
// FIXME: ?? ft.addvalue = phdri[k].p_vaddr;
|
||||
}
|
||||
x.offset = phdri[k].p_offset;
|
||||
x.size = phdri[k].p_filesz;
|
||||
if (0 == nx) {
|
||||
x.offset += sizeof(Elf_LE32_Ehdr) + sz_phdrs;
|
||||
x.size -= sizeof(Elf_LE32_Ehdr) + sz_phdrs;
|
||||
if (0 == nx) { // 1st PT_LOAD must cover Ehdr at 0==p_offset
|
||||
unsigned const delta = sizeof(Elf_LE32_Ehdr) + sz_phdrs;
|
||||
if (ft.id < 0x40) {
|
||||
// FIXME: ?? ft.addvalue += delta;
|
||||
}
|
||||
x.offset += delta;
|
||||
x.size -= delta;
|
||||
}
|
||||
packExtent(x, fo, total_in, total_out);
|
||||
packExtent(x, total_in, total_out,
|
||||
((Elf_LE32_Phdr::PF_X & phdri[k].p_flags)
|
||||
? &ft : 0 ), fo );
|
||||
++nx;
|
||||
}
|
||||
if (ptload0hi < ptload1lo) { // alignment hole?
|
||||
if (0!=ptload1sz && ptload0hi < ptload1lo) { // alignment hole?
|
||||
x.offset = 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
|
||||
x.offset = 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)
|
||||
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,
|
||||
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) {
|
||||
fi->readx(ibuf, 8);
|
||||
int const sz_unc = ph.u_len = get_native32(ibuf+0);
|
||||
int const sz_cpr = ph.c_len = get_native32(ibuf+4);
|
||||
fi->readx(&hdr, szb_info);
|
||||
int const sz_unc = ph.u_len = get_native32(&hdr.sz_unc);
|
||||
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
|
||||
throwCompressedDataViolation();
|
||||
@@ -391,15 +361,34 @@ void PackLinuxI386elf::unpackExtent(unsigned wanted, OutputFile *fo,
|
||||
int j = blocksize + OVERHEAD - sz_cpr;
|
||||
fi->readx(ibuf+j, sz_cpr);
|
||||
// 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
|
||||
if (sz_cpr < sz_unc)
|
||||
{
|
||||
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;
|
||||
}
|
||||
// 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_out += sz_unc;
|
||||
// write block
|
||||
@@ -417,6 +406,16 @@ void PackLinuxI386elf::unpack(OutputFile *fo)
|
||||
Elf_LE32_Ehdr *const ehdr = (Elf_LE32_Ehdr *)bufehdr;
|
||||
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);
|
||||
p_info hbuf;
|
||||
fi->readx(&hbuf, sizeof(hbuf));
|
||||
@@ -426,9 +425,11 @@ void PackLinuxI386elf::unpack(OutputFile *fo)
|
||||
throwCantUnpack("file header corrupted");
|
||||
|
||||
ibuf.alloc(blocksize + OVERHEAD);
|
||||
fi->readx(ibuf, 2*4);
|
||||
ph.u_len = get_native32(0+ibuf);
|
||||
ph.c_len = get_native32(4+ibuf);
|
||||
b_info bhdr; memset(&bhdr, 0, sizeof(bhdr));
|
||||
fi->readx(&bhdr, szb_info);
|
||||
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.
|
||||
fi->readx(ibuf, ph.c_len);
|
||||
@@ -436,12 +437,13 @@ void PackLinuxI386elf::unpack(OutputFile *fo)
|
||||
|
||||
unsigned total_in = 0;
|
||||
unsigned total_out = 0;
|
||||
unsigned c_adler = upx_adler32(0, NULL, 0);
|
||||
unsigned u_adler = upx_adler32(0, NULL, 0);
|
||||
off_t ptload0hi=0, ptload1lo=0;
|
||||
unsigned c_adler = upx_adler32(NULL, 0);
|
||||
unsigned u_adler = upx_adler32(NULL, 0);
|
||||
off_t ptload0hi=0, ptload1lo=0, ptload1sz=0;
|
||||
|
||||
// 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) {
|
||||
if (PT_LOAD==phdr->p_type) {
|
||||
if (0==ptload0hi) {
|
||||
@@ -449,31 +451,42 @@ void PackLinuxI386elf::unpack(OutputFile *fo)
|
||||
}
|
||||
else if (0==ptload1lo) {
|
||||
ptload1lo = phdr->p_offset;
|
||||
ptload1sz = phdr->p_filesz;
|
||||
}
|
||||
if (fo)
|
||||
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)
|
||||
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 (fo)
|
||||
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
|
||||
fi->readx(ibuf, 2*4);
|
||||
unsigned const sz_unc = ph.u_len = get_native32(ibuf+0);
|
||||
fi->readx(&bhdr, szb_info);
|
||||
unsigned const sz_unc = ph.u_len = get_native32(&bhdr.sz_unc);
|
||||
|
||||
if (sz_unc == 0) { // uncompressed size 0 -> EOF
|
||||
// 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
|
||||
throwCompressedDataViolation();
|
||||
}
|
||||
|
||||
+16
-17
@@ -2,9 +2,9 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
Copyright (C) 2000 John F. Reiser
|
||||
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
|
||||
@@ -22,11 +22,8 @@
|
||||
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
|
||||
|
||||
John F. Reiser
|
||||
jreiser@BitWagon.com
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar John F. Reiser
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu jreiser@BitWagon.com
|
||||
*/
|
||||
|
||||
|
||||
@@ -44,12 +41,12 @@ class PackLinuxI386elf : public PackLinuxI386
|
||||
public:
|
||||
PackLinuxI386elf(InputFile *f);
|
||||
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 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 bool canPack();
|
||||
@@ -61,21 +58,23 @@ protected:
|
||||
off_t offset;
|
||||
off_t size;
|
||||
};
|
||||
virtual void packExtent(Extent const &x, OutputFile *fo,
|
||||
unsigned &total_in, unsigned &total_out);
|
||||
virtual void packExtent(Extent const &x,
|
||||
unsigned &total_in, unsigned &total_out, Filter *, OutputFile *);
|
||||
virtual void unpackExtent(unsigned wanted, OutputFile *fo,
|
||||
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:
|
||||
virtual const upx_byte *getLoader() const;
|
||||
virtual int getLoaderSize() const;
|
||||
virtual void pack1(OutputFile *, Filter &); // generate executable header
|
||||
virtual void pack2(OutputFile *, Filter &); // append compressed data
|
||||
|
||||
virtual void patchLoader();
|
||||
virtual void updateLoader(OutputFile *);
|
||||
|
||||
Elf_LE32_Ehdr ehdri; // from 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.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
Copyright (C) 2000 John F. Reiser
|
||||
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
|
||||
@@ -22,11 +22,8 @@
|
||||
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
|
||||
|
||||
John F. Reiser
|
||||
jreiser@BitWagon.com
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar John F. Reiser
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu jreiser@BitWagon.com
|
||||
*/
|
||||
|
||||
|
||||
@@ -36,6 +33,7 @@
|
||||
#include "packer.h"
|
||||
#include "p_elf.h"
|
||||
#include "p_unix.h"
|
||||
#include "p_lx_exc.h"
|
||||
#include "p_lx_elf.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
|
||||
{
|
||||
@@ -55,12 +54,12 @@ const upx_byte *PackLinuxI386sep::getLoader() const
|
||||
if (0==name) {
|
||||
name = "/usr/local/lib/upxX";
|
||||
}
|
||||
sprintf(script, "#!%s\n", name);
|
||||
if (M_IS_NRV2B(opt->method)) {
|
||||
upx_snprintf(script, sizeof(script), "#!%s\n", name);
|
||||
if (M_IS_NRV2B(ph.method)) {
|
||||
script[strlen(script)-2] = 'b';
|
||||
return (upx_byte const *)script;
|
||||
}
|
||||
if (M_IS_NRV2D(opt->method)) {
|
||||
if (M_IS_NRV2D(ph.method)) {
|
||||
script[strlen(script)-2] = 'd';
|
||||
return (upx_byte const *)script;
|
||||
}
|
||||
@@ -69,9 +68,9 @@ const upx_byte *PackLinuxI386sep::getLoader() const
|
||||
|
||||
int PackLinuxI386sep::getLoaderSize() const
|
||||
{
|
||||
if (M_IS_NRV2B(opt->method))
|
||||
if (M_IS_NRV2B(ph.method))
|
||||
return SCRIPT_SIZE;
|
||||
if (M_IS_NRV2D(opt->method))
|
||||
if (M_IS_NRV2D(ph.method))
|
||||
return SCRIPT_SIZE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
+5
-5
@@ -2,9 +2,9 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
Copyright (C) 2000 John F. Reiser
|
||||
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
|
||||
@@ -22,8 +22,8 @@
|
||||
If not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
John F. Reiser
|
||||
jreiser@BitWagon.com
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar John F. Reiser
|
||||
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.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
Copyright (C) 2000 John F. Reiser
|
||||
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
|
||||
@@ -22,128 +22,71 @@
|
||||
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
|
||||
|
||||
John F. Reiser
|
||||
jreiser@BitWagon.com
|
||||
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 "packer.h"
|
||||
#include "p_elf.h"
|
||||
#include "p_unix.h"
|
||||
#include "p_lx_exc.h"
|
||||
#include "p_lx_sh.h"
|
||||
|
||||
#define PT_LOAD Elf_LE32_Phdr::PT_LOAD
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
static const
|
||||
#include "stub/l_sh_n2b.h"
|
||||
#include "stub/l_lx_sh86.h"
|
||||
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(InputFile *f)
|
||||
:super(f)
|
||||
,o_shname(0)
|
||||
,l_shname(0)
|
||||
int
|
||||
PackLinuxI386sh::buildLoader(Filter const *ft)
|
||||
{
|
||||
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
|
||||
{
|
||||
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();
|
||||
}
|
||||
void PackLinuxI386sh::patchLoader() { }
|
||||
|
||||
|
||||
bool PackLinuxI386sh::getShellName(char *buf)
|
||||
@@ -151,15 +94,16 @@ bool PackLinuxI386sh::getShellName(char *buf)
|
||||
exetype = -1;
|
||||
l_shname = strcspn(buf, " \t\n\v\f\r");
|
||||
buf[l_shname] = 0;
|
||||
char const *const basename = 1+strrchr(buf, '/');
|
||||
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 ???
|
||||
NULL
|
||||
};
|
||||
for (int j=0; 0 != shname[j]; ++j) {
|
||||
if (0==strcmp(shname[j], basename)) {
|
||||
o_shname += 3; // space for "-c\x00"
|
||||
const char *bname = strrchr(buf, '/');
|
||||
if (bname == NULL)
|
||||
return false;
|
||||
for (int j = 0; NULL != shname[j]; ++j) {
|
||||
if (0 == strcmp(shname[j], bname + 1)) {
|
||||
return super::canPack();
|
||||
}
|
||||
}
|
||||
@@ -173,9 +117,9 @@ bool PackLinuxI386sh::canPack()
|
||||
// only compress i386sh scripts when running under Linux
|
||||
char buf[512];
|
||||
|
||||
fi->readx(buf, 512);
|
||||
fi->readx(buf, sizeof(buf));
|
||||
fi->seek(0, SEEK_SET);
|
||||
buf[511] = 0;
|
||||
buf[sizeof(buf) - 1] = 0;
|
||||
if (!memcmp(buf, "#!/", 3)) { // #!/bin/sh
|
||||
o_shname = 2;
|
||||
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)
|
||||
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
|
||||
generateElfHdr(fo, linux_i386sh_fold, 0x08048000);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et
|
||||
*/
|
||||
|
||||
+9
-14
@@ -2,9 +2,9 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
Copyright (C) 2000 John F. Reiser
|
||||
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
|
||||
@@ -22,11 +22,8 @@
|
||||
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
|
||||
|
||||
John F. Reiser
|
||||
jreiser@BitWagon.com
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar John F. Reiser
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu jreiser@BitWagon.com
|
||||
*/
|
||||
|
||||
|
||||
@@ -44,26 +41,24 @@ class PackLinuxI386sh : public PackLinuxI386
|
||||
public:
|
||||
PackLinuxI386sh(InputFile *f);
|
||||
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 const char *getName() const { return "linux/sh386"; }
|
||||
virtual const int *getFilters() const { return NULL; }
|
||||
virtual int buildLoader(const Filter *);
|
||||
|
||||
virtual void pack1(OutputFile *fo, Filter &ft);
|
||||
|
||||
virtual bool canPack();
|
||||
virtual void pack(OutputFile *fo);
|
||||
// virtual void unpack(OutputFile *fo) { super::unpack(fo); }
|
||||
virtual bool canUnpackVersion(int version) const
|
||||
{ return (version >= 11); }
|
||||
|
||||
protected:
|
||||
virtual const upx_byte *getLoader() const;
|
||||
virtual int getLoaderSize() const;
|
||||
virtual bool getShellName(char *buf);
|
||||
|
||||
virtual void patchLoader();
|
||||
|
||||
Elf_LE32_Ehdr *ehdri; // from input file
|
||||
|
||||
int o_shname; // offset to 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
|
||||
*/
|
||||
|
||||
|
||||
+20
-17
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
@@ -45,13 +45,12 @@ bool PackSys::canPack()
|
||||
{
|
||||
unsigned char buf[128];
|
||||
|
||||
fi->readx(buf,128);
|
||||
fi->readx(buf, sizeof(buf));
|
||||
if (memcmp (buf,"\xff\xff\xff\xff",4) != 0)
|
||||
return false;
|
||||
if (!fn_has_ext(fi->getName(),"sys"))
|
||||
return false;
|
||||
if (find_le32(buf,128,UPX_MAGIC_LE32) >= 0)
|
||||
throwAlreadyPacked();
|
||||
checkAlreadyPacked(buf, sizeof(buf));
|
||||
if (file_size < 1024)
|
||||
throwCantPack("file is too small");
|
||||
if (file_size > 0x10000)
|
||||
@@ -66,21 +65,21 @@ bool PackSys::canPack()
|
||||
|
||||
void PackSys::patchLoader(OutputFile *fo,
|
||||
upx_byte *loader, int lsize,
|
||||
unsigned calls, unsigned overlapoh)
|
||||
unsigned calls)
|
||||
{
|
||||
const int filter_id = ph.filter;
|
||||
const int e_len = getLoaderSection("SYSCUTPO");
|
||||
const int e_len = getLoaderSectionStart("SYSCUTPO");
|
||||
const int d_len = lsize - e_len;
|
||||
assert(e_len > 0 && e_len < 256);
|
||||
assert(d_len > 0 && d_len < 256);
|
||||
|
||||
if (ph.u_len + d_len + overlapoh > 0xfffe)
|
||||
if (ph.u_len + d_len + ph.overlap_overhead > 0xfffe)
|
||||
throwNotCompressible();
|
||||
|
||||
memcpy(loader,ibuf,6); // copy from orig. header
|
||||
memcpy(loader+8,ibuf+8,2); // opendos wants this word too
|
||||
|
||||
unsigned copy_to = ph.u_len + d_len + overlapoh;
|
||||
unsigned copy_to = ph.u_len + d_len + ph.overlap_overhead;
|
||||
|
||||
patch_le16(loader,lsize,"JO",get_le16(ibuf+6)-copy_to-1);
|
||||
if (filter_id)
|
||||
@@ -88,10 +87,11 @@ void PackSys::patchLoader(OutputFile *fo,
|
||||
assert(calls > 0);
|
||||
patch_le16(loader,lsize,"CT",calls);
|
||||
}
|
||||
patchPackHeader(loader,e_len);
|
||||
|
||||
const unsigned jmp_pos = find_le16(loader,e_len,get_le16("JM"));
|
||||
patch_le16(loader,e_len,"JM",ph.u_len+overlapoh+2-jmp_pos-2);
|
||||
loader[getLoaderSection("SYSSUBSI") - 1] = (upx_byte) -e_len;
|
||||
patch_le16(loader,e_len,"JM",ph.u_len+ph.overlap_overhead+2-jmp_pos-2);
|
||||
loader[getLoaderSectionStart("SYSSUBSI") - 1] = (upx_byte) -e_len;
|
||||
patch_le16(loader,e_len,"DI",copy_to);
|
||||
patch_le16(loader,e_len,"SI",ph.c_len+e_len+d_len-1);
|
||||
|
||||
@@ -104,19 +104,22 @@ void PackSys::patchLoader(OutputFile *fo,
|
||||
|
||||
int PackSys::buildLoader(const Filter *ft)
|
||||
{
|
||||
const int filter_id = ft->id;
|
||||
initLoader(nrv2b_loader,sizeof(nrv2b_loader));
|
||||
addLoader("SYSMAIN1",
|
||||
opt->cpu == opt->CPU_8086 ? "SYSI0861" : "SYSI2861",
|
||||
"SYSMAIN2""SYSSUBSI",
|
||||
filter_id ? "SYSCALLT" : "",
|
||||
ph.first_offset_found == 1 ? "SYSSBBBP" : "",
|
||||
ft->id ? "SYSCALLT" : "",
|
||||
"SYSMAIN3""UPX1HEAD""SYSCUTPO""NRV2B160""NRVDDONE""NRVDECO1",
|
||||
ph.max_offset_found <= 0xd00 ? "NRVLED00" : "NRVGTD00",
|
||||
"NRVDECO2""NRV2B169",
|
||||
NULL
|
||||
);
|
||||
if (filter_id)
|
||||
addFilter16(filter_id);
|
||||
if (ft->id)
|
||||
{
|
||||
assert(ft->calls > 0);
|
||||
addFilter16(ft->id);
|
||||
}
|
||||
addLoader("SYSMAIN5",
|
||||
opt->cpu == opt->CPU_8086 ? "SYSI0862" : "SYSI2862",
|
||||
"SYSJUMP1",
|
||||
|
||||
+6
-6
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ class PackSys : public PackCom
|
||||
typedef PackCom super;
|
||||
public:
|
||||
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 const char *getName() const { return "dos/sys"; }
|
||||
|
||||
@@ -50,7 +50,7 @@ protected:
|
||||
|
||||
protected:
|
||||
virtual int buildLoader(const Filter *ft);
|
||||
virtual void patchLoader(OutputFile *fo, upx_byte *, int, unsigned, unsigned);
|
||||
virtual void patchLoader(OutputFile *fo, upx_byte *, int, unsigned);
|
||||
};
|
||||
|
||||
|
||||
|
||||
+85
-67
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,10 +21,11 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
#include "file.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))
|
||||
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;
|
||||
COMPILE_TIME_ASSERT(sizeof(tmt_header_t) == 44);
|
||||
}
|
||||
|
||||
|
||||
const int *PackTmt::getCompressionMethods(int method, int level) const
|
||||
{
|
||||
return Packer::getDefaultCompressionMethods_le32(method, level);
|
||||
}
|
||||
|
||||
|
||||
const int *PackTmt::getFilters() const
|
||||
{
|
||||
static const int filters[] = { 0x26, 0x24, 0x11, 0x14, 0x13, 0x16,
|
||||
0x25, 0x12, 0x15, -1 };
|
||||
static const int filters[] = {
|
||||
0x26, 0x24, 0x11, 0x14, 0x13, 0x16, 0x25, 0x12, 0x15,
|
||||
-1 };
|
||||
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 H4(x) get_le32(h,x)
|
||||
#define H(x) get_le16(h+2*(x))
|
||||
#define H4(x) get_le32(h+(x))
|
||||
unsigned char h[0x40];
|
||||
int ic;
|
||||
unsigned exe_offset = 0;
|
||||
@@ -111,14 +152,16 @@ bool PackTmt::readFileHeader()
|
||||
else if (memcmp(h,"Adam",4) == 0)
|
||||
break;
|
||||
else
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
if (ic == 20)
|
||||
return false;
|
||||
return 0;
|
||||
|
||||
fi->seek(adam_offset,SEEK_SET);
|
||||
fi->readx(&ih,sizeof(ih));
|
||||
// FIXME: should add some checks for the values in `ih'
|
||||
|
||||
return true;
|
||||
return UPX_F_TMT_ADAM;
|
||||
#undef H4
|
||||
#undef H
|
||||
}
|
||||
@@ -126,7 +169,9 @@ bool PackTmt::readFileHeader()
|
||||
|
||||
bool PackTmt::canPack()
|
||||
{
|
||||
return readFileHeader();
|
||||
if (!readFileHeader())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -136,6 +181,8 @@ bool PackTmt::canPack()
|
||||
|
||||
void PackTmt::pack(OutputFile *fo)
|
||||
{
|
||||
big_relocs = 0;
|
||||
|
||||
Packer::handleStub(fi,fo,adam_offset);
|
||||
|
||||
const unsigned usize = ih.imagesize;
|
||||
@@ -160,18 +207,13 @@ void PackTmt::pack(OutputFile *fo)
|
||||
checkOverlay(overlay);
|
||||
|
||||
unsigned relocsize = 0;
|
||||
int big;
|
||||
//if (rsize)
|
||||
{
|
||||
for (unsigned ic=4; ic<=rsize; 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;
|
||||
set_le32(wrkmem+relocsize,ih.entry); // save original entry point
|
||||
relocsize += 4;
|
||||
@@ -179,61 +221,36 @@ void PackTmt::pack(OutputFile *fo)
|
||||
relocsize += 4;
|
||||
memcpy(ibuf+usize,wrkmem,relocsize);
|
||||
|
||||
ph.filter = ft.id;
|
||||
ph.filter_cto = ft.cto;
|
||||
ph.u_len = usize+relocsize;
|
||||
if (!compress(ibuf,obuf))
|
||||
throwNotCompressible();
|
||||
// make sure the decompressor will be paragraph aligned
|
||||
const unsigned overlapoh = ((findOverlapOverhead(obuf,512)+0x20)
|
||||
&~ 0xf) - (ph.u_len & 0xf);
|
||||
|
||||
// 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
|
||||
);
|
||||
// prepare packheader
|
||||
ph.u_len = usize + relocsize;
|
||||
// prepare filter
|
||||
Filter ft(ph.level);
|
||||
ft.buf_len = usize;
|
||||
// compress
|
||||
compressWithFilters(&ft, 512);
|
||||
|
||||
const unsigned lsize = getLoaderSize();
|
||||
MemBuffer loader(lsize);
|
||||
memcpy(loader,getLoader(),lsize);
|
||||
|
||||
const unsigned s_point = getLoaderSection("TMTMAIN1");
|
||||
int e_len = getLoaderSection("TMTCUTPO");
|
||||
int e_len = getLoaderSectionStart("TMTCUTPO");
|
||||
const unsigned d_len = lsize - e_len;
|
||||
assert(e_len > 0 && s_point > 0);
|
||||
|
||||
// patch loader
|
||||
patch_le32(loader,lsize,"JMPO",ih.entry-(ph.u_len+overlapoh+d_len));
|
||||
patch_le32(loader,lsize,"JMPO",ih.entry-(ph.u_len+ph.overlap_overhead+d_len));
|
||||
patchFilter32(loader, lsize, &ft);
|
||||
patchPackHeader(loader,e_len);
|
||||
|
||||
const unsigned jmp_pos = find_le32(loader,e_len,get_le32("JMPD"));
|
||||
patch_le32(loader,e_len,"JMPD",ph.u_len+overlapoh-jmp_pos-4);
|
||||
patch_le32(loader,e_len,"JMPD",ph.u_len+ph.overlap_overhead-jmp_pos-4);
|
||||
|
||||
patch_le32(loader,e_len,"ECX0",ph.c_len+d_len);
|
||||
patch_le32(loader,e_len,"EDI0",ph.u_len+overlapoh+d_len-1);
|
||||
patch_le32(loader,e_len,"EDI0",ph.u_len+ph.overlap_overhead+d_len-1);
|
||||
patch_le32(loader,e_len,"ESI0",ph.c_len+e_len+d_len-1);
|
||||
//fprintf(stderr,"\nelen=%x dlen=%x copy_len=%x copy_to=%x oo=%x jmp_pos=%x ulen=%x clen=%x \n\n",
|
||||
// e_len,d_len,copy_len,copy_to,overlapoh,jmp_pos,ph.u_len,ph.c_len);
|
||||
// e_len,d_len,copy_len,copy_to,ph.overlap_overhead,jmp_pos,ph.u_len,ph.c_len);
|
||||
|
||||
memcpy(&oh,&ih,sizeof(oh));
|
||||
oh.imagesize = ph.c_len+e_len+d_len; // new size
|
||||
@@ -250,7 +267,7 @@ void PackTmt::pack(OutputFile *fo)
|
||||
fo->write(rel_entry,sizeof (rel_entry));
|
||||
|
||||
// verify
|
||||
verifyOverlappingDecompression(&obuf, overlapoh);
|
||||
verifyOverlappingDecompression();
|
||||
|
||||
// copy the overlay
|
||||
copyOverlay(fo, overlay, &obuf);
|
||||
@@ -263,9 +280,10 @@ void PackTmt::pack(OutputFile *fo)
|
||||
|
||||
int PackTmt::canUnpack()
|
||||
{
|
||||
if (!PackTmt::readFileHeader())
|
||||
if (!readFileHeader())
|
||||
return false;
|
||||
return readPackHeader(512,adam_offset) ? 1 : -1;
|
||||
fi->seek(adam_offset, SEEK_SET);
|
||||
return readPackHeader(512) ? 1 : -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -293,7 +311,7 @@ void PackTmt::unpack(OutputFile *fo)
|
||||
Filter ft(ph.level);
|
||||
ft.init(ph.filter, 0);
|
||||
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
|
||||
|
||||
+15
-9
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
@@ -38,11 +38,11 @@ class PackTmt : public Packer
|
||||
{
|
||||
typedef Packer super;
|
||||
public:
|
||||
PackTmt(InputFile *f) : super(f) { assert(sizeof(tmt_header_t) == 44); }
|
||||
virtual int getVersion() const { return 11; }
|
||||
PackTmt(InputFile *f);
|
||||
virtual int getVersion() const { return 13; }
|
||||
virtual int getFormat() const { return UPX_F_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 void pack(OutputFile *fo);
|
||||
@@ -52,9 +52,15 @@ public:
|
||||
virtual int canUnpack();
|
||||
|
||||
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;
|
||||
int big_relocs;
|
||||
|
||||
struct tmt_header_t
|
||||
{
|
||||
@@ -64,7 +70,7 @@ protected:
|
||||
LE32 entry;
|
||||
char ___[12]; // esp,numfixups,flags
|
||||
LE32 relocsize;
|
||||
} ih,oh;
|
||||
} ih, oh;
|
||||
};
|
||||
|
||||
|
||||
|
||||
+138
-67
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,14 +21,15 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
|
||||
#include "file.h"
|
||||
#include "filter.h"
|
||||
#include "packer.h"
|
||||
#include "p_tos.h"
|
||||
|
||||
@@ -40,6 +41,10 @@ static const
|
||||
#include "stub/l_t_n2d.h"
|
||||
static const
|
||||
#include "stub/l_t_n2ds.h"
|
||||
static const
|
||||
#include "stub/l_t_n2e.h"
|
||||
static const
|
||||
#include "stub/l_t_n2es.h"
|
||||
|
||||
// #define TESTING
|
||||
|
||||
@@ -53,17 +58,14 @@ static const
|
||||
PackTos::PackTos(InputFile *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))
|
||||
return M_NRV2B_8;
|
||||
if (M_IS_NRV2D(opt->method))
|
||||
return M_NRV2D_8;
|
||||
return opt->level > 1 && file_size >= 512*1024 ? M_NRV2D_8 : M_NRV2B_8;
|
||||
bool small = ih.fh_text + ih.fh_data <= 256*1024;
|
||||
return Packer::getDefaultCompressionMethods_8(method, level, small);
|
||||
}
|
||||
|
||||
|
||||
@@ -75,20 +77,24 @@ const int *PackTos::getFilters() 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;
|
||||
if (M_IS_NRV2D(opt->method))
|
||||
if (M_IS_NRV2D(ph.method))
|
||||
return opt->small ? nrv2d_loader_small : nrv2d_loader;
|
||||
if (M_IS_NRV2E(ph.method))
|
||||
return opt->small ? nrv2e_loader_small : nrv2e_loader;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
if (M_IS_NRV2D(opt->method))
|
||||
if (M_IS_NRV2D(ph.method))
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -132,15 +138,15 @@ int PackTos::getLoaderSize() const
|
||||
// util
|
||||
**************************************************************************/
|
||||
|
||||
bool PackTos::readFileHeader()
|
||||
int PackTos::readFileHeader()
|
||||
{
|
||||
fi->seek(0,SEEK_SET);
|
||||
fi->readx(&ih, FH_SIZE);
|
||||
if (ih.fh_magic != 0x601a)
|
||||
return false;
|
||||
return 0;
|
||||
if (FH_SIZE + ih.fh_text + ih.fh_data + ih.fh_sym > (unsigned) file_size)
|
||||
return false;
|
||||
return true;
|
||||
return 0;
|
||||
return UPX_F_ATARI_TOS;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
const char *subq_marker)
|
||||
unsigned PackTos::patch_d_subq(void *b, int blen,
|
||||
int d_reg, unsigned d_value,
|
||||
const char *subq_marker)
|
||||
{
|
||||
// patch a "subq.l #1,d0" or "subq.w #1,d0".
|
||||
// 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)
|
||||
throwBadLoader();
|
||||
|
||||
unsigned char *p = (unsigned char *)b + boff;
|
||||
if (p[2] == 0x66) // bne.b XXX
|
||||
upx_byte *p = (upx_byte *)b + boff;
|
||||
if (p[2] == 0x66) // bne.b XXX
|
||||
checkPatch(b, blen, boff, 4);
|
||||
else
|
||||
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
|
||||
{
|
||||
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
|
||||
int branch = (signed char) p[3];
|
||||
set_be16(p+2, branch+2);
|
||||
// adjust d0
|
||||
d0 -= 1;
|
||||
d_value -= 1;
|
||||
}
|
||||
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,
|
||||
const char *d0_marker, const char *subq_marker)
|
||||
unsigned PackTos::patch_d_loop(void *b, int blen,
|
||||
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);
|
||||
|
||||
unsigned char *p = (unsigned char *)b + boff;
|
||||
assert(get_be16(p - 2) == 0x203c); // move.l #XXXXXXXX,d0
|
||||
set_be32(p, d0);
|
||||
|
||||
return d0;
|
||||
upx_byte *p = (upx_byte *)b + boff;
|
||||
assert(get_be16(p - 2) == OP_MOVEI_L(d_reg)); // move.l #XXXXXXXX,d0
|
||||
set_be32(p, d_value);
|
||||
return d_value;
|
||||
}
|
||||
|
||||
|
||||
@@ -262,7 +321,7 @@ static int check_relocs(const upx_byte *relocs, unsigned rsize, unsigned isize,
|
||||
return -1;
|
||||
if (i >= rsize) // premature EOF in relocs
|
||||
return -1;
|
||||
int c = relocs[i++];
|
||||
unsigned c = relocs[i++];
|
||||
if (c == 0) // end marker
|
||||
break;
|
||||
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()
|
||||
{
|
||||
#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())
|
||||
return false;
|
||||
|
||||
unsigned char buf[512];
|
||||
fi->readx(buf,sizeof(buf));
|
||||
if (find_le32(buf,sizeof(buf),UPX_MAGIC_LE32) >= 0)
|
||||
throwAlreadyPacked();
|
||||
fi->readx(buf, sizeof(buf));
|
||||
checkAlreadyPacked(buf, sizeof(buf));
|
||||
|
||||
if (!checkFileHeader())
|
||||
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);
|
||||
#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.
|
||||
int r = 0;
|
||||
if (overlay < 4)
|
||||
@@ -407,14 +477,15 @@ void PackTos::pack(OutputFile *fo)
|
||||
// alloc buffer
|
||||
obuf.allocForCompression(t + d_len + 512);
|
||||
|
||||
// compress (max_match = 65535)
|
||||
// prepare packheader
|
||||
ph.u_len = t;
|
||||
if (!compress(ibuf,obuf,0,65535))
|
||||
throwNotCompressible();
|
||||
// prepare filter
|
||||
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:
|
||||
const unsigned overlapoh = findOverlapOverhead(obuf, 512);
|
||||
unsigned offset = (ph.u_len + overlapoh) - ph.c_len;
|
||||
unsigned offset = (ph.u_len + ph.overlap_overhead) - ph.c_len;
|
||||
|
||||
// compute addresses
|
||||
unsigned o_text, o_data, o_bss;
|
||||
@@ -456,8 +527,8 @@ void PackTos::pack(OutputFile *fo)
|
||||
while (dirty_bss & (dirty_bss_align - 1))
|
||||
dirty_bss++;
|
||||
// adjust bss, assert room for some stack
|
||||
if (dirty_bss + 256 > o_bss)
|
||||
o_bss = dirty_bss + 256;
|
||||
if (dirty_bss + 512 > o_bss)
|
||||
o_bss = dirty_bss + 512;
|
||||
|
||||
// dword align the len of the final bss segment
|
||||
while (o_bss & 3)
|
||||
@@ -471,12 +542,12 @@ void PackTos::pack(OutputFile *fo)
|
||||
patchPackHeader(loader,o_text);
|
||||
if (!opt->small)
|
||||
patchVersion(loader,o_text);
|
||||
// patch "subq.l #1,d0" or "subq.w #1,d0" - see "up41" below
|
||||
const unsigned dirty_bss_d0 =
|
||||
patch_d0_subq(loader, o_text, dirty_bss / dirty_bss_align, "u4");
|
||||
patch_be32(loader,o_text,"up31",d_off + offset + decomp_offset);
|
||||
// patch "subq.l #1,d6" or "subq.w #1,d6" - see "up41" below
|
||||
const unsigned dirty_bss_d6 =
|
||||
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);
|
||||
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
|
||||
{
|
||||
if (o_data <= 160)
|
||||
@@ -488,8 +559,8 @@ void PackTos::pack(OutputFile *fo)
|
||||
loop1--;
|
||||
loop2 = 160;
|
||||
}
|
||||
patch_be16(loader,o_text,"u2", 0x7000 + loop2/4-1); // moveq.l #X,d0
|
||||
patch_d0_loop(loader,o_text,loop1,"up22","u1");
|
||||
patch_be16(loader, o_text, "u2", OP_MOVEQ(loop2/4-1, REG_D0)); // moveq.l #X,d0
|
||||
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,"up13",i_bss); // p_blen
|
||||
@@ -498,9 +569,9 @@ void PackTos::pack(OutputFile *fo)
|
||||
|
||||
// patch decompressor
|
||||
upx_byte *p = obuf + d_off;
|
||||
// patch "moveq.l #1,d3" or "jmp (a5)"
|
||||
patch_be16(p,d_len,"u3", (nrelocs > 0) ? 0x7601 : 0x4ed5);
|
||||
patch_be32(p,d_len,"up41", dirty_bss_d0);
|
||||
// patch "moveq.l #1,d5" or "jmp (ASTACK)"
|
||||
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_d6);
|
||||
|
||||
// set new file_hdr
|
||||
memcpy(&oh, &ih, FH_SIZE);
|
||||
@@ -539,7 +610,7 @@ void PackTos::pack(OutputFile *fo)
|
||||
fo->write("\x00\x00\x00\x00",4);
|
||||
|
||||
// verify
|
||||
verifyOverlappingDecompression(&obuf, overlapoh);
|
||||
verifyOverlappingDecompression();
|
||||
|
||||
// copy the overlay
|
||||
copyOverlay(fo, overlay, &obuf);
|
||||
@@ -558,7 +629,7 @@ int PackTos::canUnpack()
|
||||
{
|
||||
if (!readFileHeader())
|
||||
return false;
|
||||
if (!readPackHeader(512, 0))
|
||||
if (!readPackHeader(768))
|
||||
return false;
|
||||
// check header as set by packer
|
||||
if ((ih.fh_text & 3) != 0 || (ih.fh_data & 3) != 0 || (ih.fh_bss & 3) != 0
|
||||
|
||||
+14
-11
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
@@ -39,10 +39,10 @@ class PackTos : public Packer
|
||||
typedef Packer super;
|
||||
public:
|
||||
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 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 void pack(OutputFile *fo);
|
||||
@@ -57,8 +57,8 @@ protected:
|
||||
virtual const upx_byte *getLoader() const;
|
||||
virtual int getLoaderSize() const;
|
||||
|
||||
bool readFileHeader();
|
||||
bool checkFileHeader();
|
||||
virtual int readFileHeader();
|
||||
virtual bool checkFileHeader();
|
||||
|
||||
struct tos_header_t
|
||||
{
|
||||
@@ -70,11 +70,14 @@ protected:
|
||||
BE32 fh_reserved;
|
||||
BE32 fh_flag;
|
||||
BE16 fh_reloc;
|
||||
} ih, oh;
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
tos_header_t ih, oh;
|
||||
|
||||
protected:
|
||||
unsigned patch_d0_subq(void *b, int blen, unsigned, const char*);
|
||||
unsigned patch_d0_loop(void *b, int blen, unsigned, const char*, const char*);
|
||||
unsigned patch_d_subq(void *l, int llen, int, unsigned, const char*);
|
||||
unsigned patch_d_loop(void *l, int llen, int, unsigned, const char*, const char*);
|
||||
};
|
||||
|
||||
|
||||
|
||||
+225
-312
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,14 +21,15 @@
|
||||
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
|
||||
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_unix.h"
|
||||
#include "p_elf.h"
|
||||
@@ -44,10 +45,11 @@
|
||||
PackUnix::PackUnix(InputFile *f) :
|
||||
super(f), exetype(0), blocksize(0), overlay_offset(0), lsize(0)
|
||||
{
|
||||
assert(sizeof(Elf_LE32_Ehdr) == 52);
|
||||
assert(sizeof(Elf_LE32_Phdr) == 32);
|
||||
assert(sizeof(l_info) == 12);
|
||||
assert(sizeof(p_info) == 12);
|
||||
COMPILE_TIME_ASSERT(sizeof(Elf_LE32_Ehdr) == 52);
|
||||
COMPILE_TIME_ASSERT(sizeof(Elf_LE32_Phdr) == 32);
|
||||
COMPILE_TIME_ASSERT(sizeof(b_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
|
||||
unsigned char buf[256];
|
||||
fi->seek(-(long)sizeof(buf), SEEK_END);
|
||||
fi->readx(buf,sizeof(buf));
|
||||
if (find_le32(buf,sizeof(buf),UPX_MAGIC_LE32) >= 0) // note: always le32
|
||||
throwAlreadyPacked();
|
||||
fi->seek(-(off_t)sizeof(buf), SEEK_END);
|
||||
fi->readx(buf, sizeof(buf));
|
||||
checkAlreadyPacked(buf, sizeof(buf));
|
||||
|
||||
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().
|
||||
//
|
||||
@@ -94,107 +115,170 @@ bool PackUnix::checkCompressionRatio(unsigned, unsigned) const
|
||||
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)
|
||||
{
|
||||
Filter ft(ph.level);
|
||||
ft.addvalue = 0;
|
||||
b_len = 0;
|
||||
progid = 0;
|
||||
|
||||
// set options
|
||||
blocksize = opt->unix.blocksize;
|
||||
if (blocksize <= 0)
|
||||
blocksize = BLOCKSIZE;
|
||||
if ((off_t)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
|
||||
ibuf.alloc(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);
|
||||
for (;;)
|
||||
{
|
||||
int l = fi->read(ibuf, blocksize);
|
||||
if (l == 0)
|
||||
break;
|
||||
pack1(fo, ft); // generate Elf header, etc.
|
||||
|
||||
// Note: compression for a block can fail if the
|
||||
// file is e.g. blocksize + 1 bytes long
|
||||
p_info hbuf;
|
||||
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
|
||||
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();
|
||||
pack2(fo, ft); // append the compressed body
|
||||
|
||||
// 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
|
||||
ph.u_len = total_in;
|
||||
ph.c_len = total_out;
|
||||
pack3(fo, ft); // append loader
|
||||
|
||||
// write packheader
|
||||
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);
|
||||
pack4(fo, ft); // append PackHeader and overlay_offset; update Elf header
|
||||
|
||||
// finally check the compression ratio
|
||||
if (!checkFinalCompressionRatio(fo))
|
||||
@@ -212,7 +296,8 @@ int PackUnix::canUnpack()
|
||||
const int bufsize = sizeof(buf);
|
||||
|
||||
fi->seek(-bufsize, SEEK_END);
|
||||
if (!readPackHeader(128, -1, buf))
|
||||
fi->readx(buf, bufsize);
|
||||
if (!getPackHeader(buf, bufsize))
|
||||
return false;
|
||||
|
||||
int l = ph.buf_offset + ph.getPackHeaderSize();
|
||||
@@ -235,8 +320,28 @@ int PackUnix::canUnpack()
|
||||
|
||||
void PackUnix::unpack(OutputFile *fo)
|
||||
{
|
||||
unsigned c_adler = upx_adler32(0, NULL, 0);
|
||||
unsigned u_adler = upx_adler32(0, NULL, 0);
|
||||
unsigned szb_info = sizeof(b_info);
|
||||
{
|
||||
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
|
||||
unsigned orig_file_size = 0;
|
||||
@@ -264,46 +369,52 @@ void PackUnix::unpack(OutputFile *fo)
|
||||
// decompress blocks
|
||||
unsigned total_in = 0;
|
||||
unsigned total_out = 0;
|
||||
b_info bhdr; memset(&bhdr, 0, sizeof(bhdr));
|
||||
for (;;)
|
||||
{
|
||||
#define buf ibuf
|
||||
int i;
|
||||
int size[2];
|
||||
unsigned sz_unc, sz_cpr;
|
||||
|
||||
fi->readx(buf, 8);
|
||||
ph.u_len = size[0] = get_native32(buf+0);
|
||||
ph.c_len = size[1] = get_native32(buf+4);
|
||||
fi->readx(&bhdr, szb_info);
|
||||
ph.u_len = sz_unc = get_native32(&bhdr.sz_unc);
|
||||
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
|
||||
size[1] = get_le32(buf+4);
|
||||
if (size[1] != UPX_MAGIC_LE32) // size[1] must be h->magic
|
||||
// note: must reload sz_cpr as magic is always stored le32
|
||||
sz_cpr = get_le32(&bhdr.sz_cpr);
|
||||
if (sz_cpr != UPX_MAGIC_LE32) // sz_cpr must be h->magic
|
||||
throwCompressedDataViolation();
|
||||
break;
|
||||
}
|
||||
if (size[0] <= 0 || size[1] <= 0)
|
||||
if (sz_unc <= 0 || sz_cpr <= 0)
|
||||
throwCompressedDataViolation();
|
||||
if (size[1] > size[0] || size[0] > (int)blocksize)
|
||||
if (sz_cpr > sz_unc || sz_unc > blocksize)
|
||||
throwCompressedDataViolation();
|
||||
|
||||
i = blocksize + OVERHEAD - size[1];
|
||||
fi->readx(buf+i, size[1]);
|
||||
i = blocksize + OVERHEAD - sz_cpr;
|
||||
fi->readx(buf+i, sz_cpr);
|
||||
// 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
|
||||
if (size[1] < size[0])
|
||||
{
|
||||
if (sz_cpr < sz_unc) {
|
||||
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;
|
||||
}
|
||||
// update checksum of uncompressed data
|
||||
u_adler = upx_adler32(u_adler, buf + i, size[0]);
|
||||
total_in += size[1];
|
||||
total_out += size[0];
|
||||
u_adler = upx_adler32(buf + i, sz_unc, u_adler);
|
||||
total_in += sz_cpr;
|
||||
total_out += sz_unc;
|
||||
// write block
|
||||
if (fo)
|
||||
fo->write(buf + i, size[0]);
|
||||
fo->write(buf + i, sz_unc);
|
||||
#undef buf
|
||||
}
|
||||
|
||||
@@ -321,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
|
||||
*/
|
||||
|
||||
+44
-48
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<mfx@users.sourceforge.net> <ml1050@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
@@ -41,8 +41,9 @@ class PackUnix : public Packer
|
||||
protected:
|
||||
PackUnix(InputFile *f);
|
||||
public:
|
||||
virtual int getVersion() const { return 11; }
|
||||
virtual int getVersion() const { return 13; }
|
||||
virtual const int *getFilters() const { return NULL; }
|
||||
virtual int getStrategy(Filter &);
|
||||
|
||||
virtual void pack(OutputFile *fo);
|
||||
virtual void unpack(OutputFile *fo);
|
||||
@@ -52,14 +53,21 @@ public:
|
||||
|
||||
protected:
|
||||
// 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 patchLoaderChecksum() {}
|
||||
virtual void updateLoader(OutputFile *) = 0;
|
||||
|
||||
virtual void writePackHeader(OutputFile *fo);
|
||||
|
||||
// in order too share as much code as possible we introduce
|
||||
// an endian abstraction here
|
||||
virtual unsigned get_native32(const void *, int off=0) = 0;
|
||||
virtual void set_native32(void *, unsigned, int off=0) = 0;
|
||||
virtual unsigned get_native32(const void *) = 0;
|
||||
virtual void set_native32(void *, unsigned) = 0;
|
||||
|
||||
virtual bool checkCompressionRatio(unsigned, unsigned) const;
|
||||
|
||||
@@ -70,6 +78,21 @@ protected:
|
||||
|
||||
MemBuffer loader;
|
||||
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
|
||||
unsigned l_checksum;
|
||||
@@ -77,12 +100,15 @@ protected:
|
||||
unsigned short l_lsize;
|
||||
unsigned char l_version;
|
||||
unsigned char l_format;
|
||||
};
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
struct p_info { // 12-byte packed program header
|
||||
unsigned p_progid;
|
||||
unsigned p_filesize;
|
||||
unsigned p_blocksize;
|
||||
};
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
// do not change !!!
|
||||
enum { OVERHEAD = 2048 };
|
||||
@@ -99,13 +125,13 @@ class PackUnixBe32 : public PackUnix
|
||||
typedef PackUnix super;
|
||||
protected:
|
||||
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;
|
||||
protected:
|
||||
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
|
||||
**************************************************************************/
|
||||
@@ -177,7 +173,7 @@ protected:
|
||||
|
||||
virtual void patchLoader();
|
||||
};
|
||||
#endif
|
||||
#endif /* #if 0 */
|
||||
|
||||
|
||||
#endif /* already included */
|
||||
|
||||
+148
-72
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
@@ -52,24 +52,21 @@ static const unsigned bzimage_offset = 0x100000;
|
||||
PackVmlinuzI386::PackVmlinuzI386(InputFile *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 M_NRV2B_LE32;
|
||||
if (M_IS_NRV2D(opt->method))
|
||||
return M_NRV2D_LE32;
|
||||
return opt->level > 1 ? M_NRV2D_LE32 : M_NRV2B_LE32;
|
||||
return Packer::getDefaultCompressionMethods_le32(method, level);
|
||||
}
|
||||
|
||||
|
||||
const int *PackVmlinuzI386::getFilters() const
|
||||
{
|
||||
static const int filters[] = { 0x26, 0x24, 0x11, 0x14, 0x13, 0x16,
|
||||
0x25, 0x15, 0x12, -1 };
|
||||
static const int filters[] = {
|
||||
0x26, 0x24, 0x11, 0x14, 0x13, 0x16, 0x25, 0x15, 0x12,
|
||||
-1 };
|
||||
return filters;
|
||||
}
|
||||
|
||||
@@ -88,51 +85,126 @@ int PackVmlinuzI386::readFileHeader()
|
||||
{
|
||||
boot_sect_t h;
|
||||
|
||||
setup_size = 0;
|
||||
|
||||
fi->readx(&h, sizeof(h));
|
||||
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;
|
||||
if (setup_size <= 0 || setup_size >= file_size)
|
||||
return -1;
|
||||
if (setup_size + 16 * h.sys_size != (unsigned) ALIGN_UP(file_size, 16))
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
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
|
||||
|
||||
if (memcmp(h.hdrs, "HdrS", 4) == 0 && (h.load_flags & 1) != 0)
|
||||
return UPX_F_BVMLINUZ_i386;
|
||||
|
||||
return UPX_F_VMLINUZ_i386;
|
||||
return format;
|
||||
}
|
||||
|
||||
|
||||
// read full kernel into obuf, gzip-uncompress into ibuf,
|
||||
// return uncompressed size
|
||||
int PackVmlinuzI386::uncompressKernel()
|
||||
// read full kernel into obuf[], gzip-decompress into ibuf[],
|
||||
// return decompressed size
|
||||
int PackVmlinuzI386::decompressKernel()
|
||||
{
|
||||
// read whole kernel image
|
||||
obuf.alloc(file_size);
|
||||
fi->seek(0, SEEK_SET);
|
||||
fi->readx(obuf, file_size);
|
||||
|
||||
// estimate gzip-uncompressed kernel size & alloc buffer
|
||||
ibuf.alloc((file_size - setup_size) * 3);
|
||||
checkAlreadyPacked(obuf + setup_size, UPX_MIN(file_size - setup_size, 1024));
|
||||
|
||||
// find gzip/zlib header
|
||||
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)
|
||||
break;
|
||||
gzoff += off;
|
||||
fi->seek(gzoff, SEEK_SET);
|
||||
gzFile zf = gzdopen(fi->getFd(), "r");
|
||||
if (zf == 0)
|
||||
const int gzlen = file_size - gzoff;
|
||||
if (gzlen < 256)
|
||||
break;
|
||||
int klen = gzread(zf, ibuf, ibuf.getSize());
|
||||
if (klen >= file_size)
|
||||
// check gzip flag byte
|
||||
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 0;
|
||||
@@ -141,19 +213,17 @@ int PackVmlinuzI386::uncompressKernel()
|
||||
|
||||
void PackVmlinuzI386::readKernel()
|
||||
{
|
||||
int klen = uncompressKernel();
|
||||
int klen = decompressKernel();
|
||||
if (klen <= 0)
|
||||
throwCantPack("kernel decompression failed");
|
||||
if (klen >= (int) ibuf.getSize())
|
||||
throwCantPack("kernel decompression failed -- too big");
|
||||
|
||||
//OutputFile::dump("kernel.img", ibuf, klen);
|
||||
|
||||
// copy the setup boot code
|
||||
setup_buf.alloc(setup_size);
|
||||
memcpy(setup_buf, obuf, setup_size);
|
||||
//OutputFile::dump("setup.img", setup_buf, setup_size);
|
||||
|
||||
obuf.free();
|
||||
obuf.dealloc();
|
||||
obuf.allocForCompression(klen);
|
||||
|
||||
ph.u_len = klen;
|
||||
@@ -191,21 +261,11 @@ void PackVmlinuzI386::pack(OutputFile *fo)
|
||||
readKernel();
|
||||
|
||||
// prepare filter
|
||||
Filter ft(opt->level);
|
||||
Filter ft(ph.level);
|
||||
ft.buf_len = ph.u_len;
|
||||
ft.addvalue = kernel_entry;
|
||||
// prepare other settings
|
||||
const unsigned overlap_range = 1 << 20;
|
||||
unsigned overlapoh;
|
||||
|
||||
int strategy = -1; // try the first working filter
|
||||
if (opt->filter >= 0 && isValidFilter(opt->filter))
|
||||
// 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);
|
||||
// compress
|
||||
compressWithFilters(&ft, 1 << 20);
|
||||
|
||||
const unsigned lsize = getLoaderSize();
|
||||
MemBuffer loader(lsize);
|
||||
@@ -217,7 +277,7 @@ void PackVmlinuzI386::pack(OutputFile *fo)
|
||||
patch_le32(loader, lsize, "KEIP", kernel_entry);
|
||||
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;
|
||||
|
||||
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);
|
||||
#endif
|
||||
|
||||
// verify
|
||||
verifyOverlappingDecompression();
|
||||
|
||||
// finally check the compression ratio
|
||||
if (!checkFinalCompressionRatio(fo))
|
||||
throwNotCompressible();
|
||||
@@ -268,21 +331,11 @@ void PackBvmlinuzI386::pack(OutputFile *fo)
|
||||
readKernel();
|
||||
|
||||
// prepare filter
|
||||
Filter ft(opt->level);
|
||||
Filter ft(ph.level);
|
||||
ft.buf_len = ph.u_len;
|
||||
ft.addvalue = kernel_entry;
|
||||
// prepare other settings
|
||||
const unsigned overlap_range = 512;
|
||||
unsigned overlapoh;
|
||||
|
||||
int strategy = -1; // try the first working filter
|
||||
if (opt->filter >= 0 && isValidFilter(opt->filter))
|
||||
// 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);
|
||||
// compress
|
||||
compressWithFilters(&ft, 512);
|
||||
|
||||
// align everything to dword boundary - it is easier to handle
|
||||
unsigned clen = ph.c_len;
|
||||
@@ -300,7 +353,7 @@ void PackBvmlinuzI386::pack(OutputFile *fo)
|
||||
assert(e_len > 0);
|
||||
|
||||
const unsigned d_len4 = ALIGN_UP(lsize - e_len, 4);
|
||||
const unsigned decompr_pos = ALIGN_UP(ph.u_len + overlapoh, 16);
|
||||
const unsigned decompr_pos = ALIGN_UP(ph.u_len + ph.overlap_overhead, 16);
|
||||
const unsigned copy_size = clen + d_len4;
|
||||
const unsigned edi = decompr_pos + d_len4 - 4; // copy to
|
||||
const unsigned esi = ALIGN_UP(clen + lsize, 4) - 4; // copy from
|
||||
@@ -316,8 +369,8 @@ void PackBvmlinuzI386::pack(OutputFile *fo)
|
||||
patch_le32(loader, e_len, "KEIP", kernel_entry);
|
||||
patch_le32(loader, e_len, "STAK", stack_during_uncompression);
|
||||
|
||||
boot_sect_t *bs = (boot_sect_t *) ((unsigned char *) setup_buf);
|
||||
bs->sys_size = ALIGN_UP(lsize + clen, 16) / 16;
|
||||
boot_sect_t * const bs = (boot_sect_t *) ((unsigned char *) setup_buf);
|
||||
bs->sys_size = (ALIGN_UP(lsize + clen, 16) / 16) & 0xffff;
|
||||
|
||||
fo->write(setup_buf, setup_buf.getSize());
|
||||
fo->write(loader, e_len);
|
||||
@@ -331,7 +384,7 @@ void PackBvmlinuzI386::pack(OutputFile *fo)
|
||||
#endif
|
||||
|
||||
// verify
|
||||
verifyOverlappingDecompression(&obuf, overlapoh);
|
||||
verifyOverlappingDecompression();
|
||||
|
||||
// finally check the compression ratio
|
||||
if (!checkFinalCompressionRatio(fo))
|
||||
@@ -345,18 +398,41 @@ void PackBvmlinuzI386::pack(OutputFile *fo)
|
||||
|
||||
int PackVmlinuzI386::canUnpack()
|
||||
{
|
||||
return readFileHeader() == getFormat();
|
||||
if (readFileHeader() != getFormat())
|
||||
return false;
|
||||
fi->seek(setup_size, SEEK_SET);
|
||||
return readPackHeader(1024) ? 1 : -1;
|
||||
}
|
||||
|
||||
|
||||
void PackVmlinuzI386::unpack(OutputFile *)
|
||||
void PackVmlinuzI386::unpack(OutputFile *fo)
|
||||
{
|
||||
// no uncompression support for this format, so that
|
||||
// it is possible to remove the original deflate code (>10KB)
|
||||
|
||||
// FIXME: but we could write the uncompressed "vmlinux" image
|
||||
|
||||
throwCantUnpack("build a new kernel instead :-)");
|
||||
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 :-)");
|
||||
//fo->write(obuf, ph.u_len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+36
-8
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
@@ -39,10 +39,10 @@ class PackVmlinuzI386 : public Packer
|
||||
typedef Packer super;
|
||||
public:
|
||||
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 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 void pack(OutputFile *fo);
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
|
||||
protected:
|
||||
virtual int readFileHeader();
|
||||
virtual int uncompressKernel();
|
||||
virtual int decompressKernel();
|
||||
virtual void readKernel();
|
||||
|
||||
virtual int buildLoader(const Filter *ft);
|
||||
@@ -79,7 +79,8 @@ protected:
|
||||
|
||||
// some more uninteresting fields here ...
|
||||
// see /usr/src/linux/Documentation/i386/zero-page.txt
|
||||
};
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
MemBuffer setup_buf;
|
||||
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 */
|
||||
|
||||
|
||||
|
||||
+6
-6
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
@@ -40,10 +40,10 @@ class PackVxd : public PackWcle
|
||||
public:
|
||||
PackVxd(InputFile *f);
|
||||
~PackVxd();
|
||||
virtual int getVersion() const { return 11; }
|
||||
virtual int getVersion() const { return 13; }
|
||||
virtual int getFormat() const { return UPX_F_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 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
|
||||
*/
|
||||
|
||||
+257
-162
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
@@ -45,15 +45,37 @@ static const
|
||||
#define FILLVAL 0
|
||||
|
||||
|
||||
// keep the namespace clean
|
||||
// it would be better to use inner classes except for Interval, which
|
||||
// could be used elsewhere too
|
||||
// Some defines to keep the namespace clean.
|
||||
// It would be better to use inner classes except for Interval, which
|
||||
// could be used elsewhere too.
|
||||
|
||||
#define Interval PackW32Pe_Interval
|
||||
#define Reloc PackW32Pe_Reloc
|
||||
#define Resource PackW32Pe_Resource
|
||||
#define import_desc PackW32Pe_import_desc
|
||||
#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_section_t %d\n", (int) sizeof(pe_section_t));
|
||||
assert(sizeof(pe_header_t) == 248);
|
||||
assert(sizeof(pe_section_t) == 40);
|
||||
COMPILE_TIME_ASSERT(sizeof(pe_header_t) == 248);
|
||||
COMPILE_TIME_ASSERT(sizeof(pe_section_t) == 40);
|
||||
COMPILE_TIME_ASSERT(RT_LAST == HIGH(opt->w32pe.compress_rt));
|
||||
|
||||
isection = 0;
|
||||
oimport = 0;
|
||||
oimpdlls = 0;
|
||||
orelocs = 0;
|
||||
oexport = 0;
|
||||
otls = 0;
|
||||
oresources = 0;
|
||||
oxrelocs = 0;
|
||||
isection = NULL;
|
||||
oimport = NULL;
|
||||
oimpdlls = NULL;
|
||||
orelocs = NULL;
|
||||
oexport = NULL;
|
||||
otls = NULL;
|
||||
oresources = NULL;
|
||||
oxrelocs = NULL;
|
||||
icondir_offset = 0;
|
||||
icondir_count = 0;
|
||||
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))
|
||||
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;
|
||||
bool small = ih.codesize + ih.datasize <= 256*1024;
|
||||
return Packer::getDefaultCompressionMethods_le32(method, level, small);
|
||||
}
|
||||
|
||||
|
||||
const int *PackW32Pe::getFilters() const
|
||||
{
|
||||
static const int filters[] = { 0x26, 0x24, 0x16, 0x13, 0x14, 0x11,
|
||||
0x25, 0x15, 0x12, -1 };
|
||||
static const int filters[] = {
|
||||
0x26, 0x24, 0x16, 0x13, 0x14, 0x11, 0x25, 0x15, 0x12,
|
||||
-1 };
|
||||
return filters;
|
||||
}
|
||||
|
||||
@@ -130,9 +151,9 @@ bool PackW32Pe::testUnpackVersion(int version) const
|
||||
// util
|
||||
**************************************************************************/
|
||||
|
||||
bool PackW32Pe::readFileHeader()
|
||||
int PackW32Pe::readFileHeader()
|
||||
{
|
||||
struct h_t
|
||||
struct exe_header_t
|
||||
{
|
||||
LE16 mz;
|
||||
LE16 m512;
|
||||
@@ -141,8 +162,11 @@ bool PackW32Pe::readFileHeader()
|
||||
LE16 relocoffs;
|
||||
char __[34];
|
||||
LE32 nexepos;
|
||||
} h;
|
||||
}
|
||||
__attribute_packed;
|
||||
COMPILE_TIME_ASSERT(sizeof(exe_header_t) == 64);
|
||||
|
||||
exe_header_t h;
|
||||
int ic;
|
||||
pe_offset = 0;
|
||||
|
||||
@@ -161,16 +185,16 @@ bool PackW32Pe::readFileHeader()
|
||||
else if (get_le32(&h) == 'P' + 'E'*256)
|
||||
break;
|
||||
else
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
if (ic == 20)
|
||||
return false;
|
||||
return 0;
|
||||
fi->seek(pe_offset,SEEK_SET);
|
||||
fi->readx(&ih,sizeof(ih));
|
||||
fi->seek(0x200,SEEK_SET);
|
||||
fi->readx(&h,6);
|
||||
isrtm = memcmp(&h,"32STUB",6) == 0;
|
||||
return true;
|
||||
return UPX_F_WIN32_PE;
|
||||
}
|
||||
|
||||
|
||||
@@ -200,7 +224,7 @@ public:
|
||||
void flatten();
|
||||
|
||||
void clear();
|
||||
void dump();
|
||||
void dump() const;
|
||||
|
||||
private:
|
||||
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);
|
||||
}
|
||||
|
||||
void Interval::dump()
|
||||
void Interval::dump() const
|
||||
{
|
||||
flatten();
|
||||
printf("%d intervals:\n",ivnum);
|
||||
for (unsigned ic = 0; ic < ivnum; ic++)
|
||||
printf("%x %x\n",ivarr[ic].start,ivarr[ic].len);
|
||||
@@ -276,10 +299,17 @@ class Reloc
|
||||
{
|
||||
LE32 pagestart;
|
||||
LE32 size;
|
||||
} *rel;
|
||||
LE16 *rel1;
|
||||
void newRelocPos(void *p) { rel = (reloc*) p; rel1 = (LE16*) ((char*) p + sizeof (reloc)); }
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
void newRelocPos(void *p)
|
||||
{
|
||||
rel = (reloc*) p;
|
||||
rel1 = (LE16*) ((char*) p + sizeof (reloc));
|
||||
}
|
||||
|
||||
reloc *rel;
|
||||
LE16 *rel1;
|
||||
unsigned counts[16];
|
||||
|
||||
public:
|
||||
@@ -293,15 +323,18 @@ public:
|
||||
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));
|
||||
unsigned pos,type;
|
||||
while (next(pos,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];
|
||||
counts[0] = 0;
|
||||
@@ -343,15 +376,14 @@ void Reloc::finish(upx_byte *&p,unsigned &siz)
|
||||
prev = pos;
|
||||
*rel1 = 0;
|
||||
rel->size = ALIGN_UP(ptr_diff(rel1,rel),4);
|
||||
newRelocPos(rel->size + (char*) rel);
|
||||
newRelocPos((char *)rel + rel->size);
|
||||
rel->pagestart = (pos >> 4) &~ 0xfff;
|
||||
}
|
||||
*rel1++ = (pos << 12) + ((pos >> 4) & 0xfff);
|
||||
}
|
||||
p = start;
|
||||
siz = ptr_diff(rel1,start) &~ 3;
|
||||
siz -= 4;
|
||||
rel->pagestart = 0; // terminating 0
|
||||
siz -= 8;
|
||||
assert(siz > 0);
|
||||
start = 0; // safety
|
||||
}
|
||||
@@ -434,10 +466,13 @@ struct import_desc
|
||||
char _[8];
|
||||
LE32 dllname;
|
||||
LE32 iat; // import address table
|
||||
};
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
void PackW32Pe::processImports(unsigned myimport) // pass 2
|
||||
{
|
||||
COMPILE_TIME_ASSERT(sizeof(import_desc) == 20);
|
||||
|
||||
// adjust import data
|
||||
for (import_desc *im = (import_desc*) oimpdlls; im->dllname; im++)
|
||||
{
|
||||
@@ -493,11 +528,12 @@ unsigned PackW32Pe::processImports() // pass 1
|
||||
if (!u2->shname) return -1;
|
||||
return strlen(u1->shname) - strlen(u2->shname);
|
||||
}
|
||||
};
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
// +1 for dllnum=0
|
||||
autoheap_array(struct udll, dlls, dllnum+1);
|
||||
autoheap_array(struct udll *, idlls, dllnum+1);
|
||||
Array(struct udll, dlls, dllnum+1);
|
||||
Array(struct udll *, idlls, dllnum+1);
|
||||
|
||||
soimport = 1024; // safety
|
||||
|
||||
@@ -679,14 +715,16 @@ unsigned PackW32Pe::processImports() // pass 1
|
||||
// This decreases compression ratio, so FIXME somehow.
|
||||
infoWarning("can't remove unneeded imports");
|
||||
ilen += sizeof(import_desc) * dllnum;
|
||||
#if defined(DEBUG)
|
||||
if (opt->verbose > 3)
|
||||
names.dump();
|
||||
#endif
|
||||
// do some work for the unpacker
|
||||
im = im_save;
|
||||
for (ic = 0; ic < dllnum; ic++)
|
||||
for (ic = 0; ic < dllnum; ic++, 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
|
||||
@@ -715,7 +753,7 @@ unsigned PackW32Pe::processImports() // pass 1
|
||||
|
||||
class Export
|
||||
{
|
||||
struct export_dir
|
||||
struct export_dir_t
|
||||
{
|
||||
char _[12]; // flags, timedate, version
|
||||
LE32 name;
|
||||
@@ -725,9 +763,10 @@ class Export
|
||||
LE32 addrtable;
|
||||
LE32 nameptrtable;
|
||||
LE32 ordinaltable;
|
||||
};
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
export_dir edir;
|
||||
export_dir_t edir;
|
||||
char *ename;
|
||||
char *functionptrs;
|
||||
char *ordinals;
|
||||
@@ -752,8 +791,9 @@ private:
|
||||
|
||||
Export::Export(char *_base) : base(_base), iv(_base)
|
||||
{
|
||||
ename = functionptrs = ordinals = 0;
|
||||
names = 0;
|
||||
COMPILE_TIME_ASSERT(sizeof(export_dir_t) == 40);
|
||||
ename = functionptrs = ordinals = NULL;
|
||||
names = NULL;
|
||||
memset(&edir,0,sizeof(edir));
|
||||
size = 0;
|
||||
}
|
||||
@@ -770,8 +810,8 @@ Export::~Export()
|
||||
|
||||
void Export::convert(unsigned eoffs,unsigned esize)
|
||||
{
|
||||
memcpy(&edir,base + eoffs,sizeof(export_dir));
|
||||
size = sizeof(export_dir);
|
||||
memcpy(&edir,base + eoffs,sizeof(export_dir_t));
|
||||
size = sizeof(export_dir_t);
|
||||
iv.add(eoffs,size);
|
||||
|
||||
unsigned len = strlen(base + edir.name) + 1;
|
||||
@@ -820,8 +860,10 @@ void Export::convert(unsigned eoffs,unsigned esize)
|
||||
iv.flatten();
|
||||
if (iv.ivnum == 1)
|
||||
iv.clear();
|
||||
#if defined(DEBUG)
|
||||
else
|
||||
iv.dump();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Export::build(char *newbase,unsigned newoffs)
|
||||
@@ -903,17 +945,35 @@ struct tls
|
||||
LE32 dataend; // VA tls init data end
|
||||
LE32 tlsindex; // VA tls index
|
||||
LE32 callbacks; // VA tls callbacks
|
||||
char _[8]; // zero init, characteristics
|
||||
};
|
||||
char _[8]; // zero init, characteristics
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
void PackW32Pe::processTls(Interval *iv) // pass 1
|
||||
{
|
||||
COMPILE_TIME_ASSERT(sizeof(tls) == 24);
|
||||
|
||||
if ((sotls = ALIGN_UP(IDSIZE(PEDIR_TLS),4)) == 0)
|
||||
return;
|
||||
|
||||
const tls * const tlsp = (const tls*) (ibuf + IDADDR(PEDIR_TLS));
|
||||
unsigned tlsdatastart = tlsp->datastart - ih.imagebase;
|
||||
unsigned tlsdataend = tlsp->dataend - ih.imagebase;
|
||||
// note: TLS callbacks are not implemented in Windows 95/98/ME
|
||||
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
|
||||
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->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 child;
|
||||
};
|
||||
}
|
||||
__attribute_packed;
|
||||
struct res_dir
|
||||
{
|
||||
char _[12]; // flags, timedate, version
|
||||
@@ -986,13 +1047,15 @@ class Resource
|
||||
res_dir_entry entries[1];
|
||||
// it's usually safe to assume that every res_dir contains
|
||||
// at least one res_dir_entry - check() complains otherwise
|
||||
};
|
||||
}
|
||||
__attribute_packed;
|
||||
struct res_data
|
||||
{
|
||||
LE32 offset;
|
||||
LE32 size;
|
||||
char _[8]; // codepage, reserved
|
||||
};
|
||||
}
|
||||
__attribute_packed;
|
||||
//
|
||||
struct upx_rnode
|
||||
{
|
||||
@@ -1029,7 +1092,7 @@ class Resource
|
||||
void destroy(upx_rnode *urd,unsigned level);
|
||||
|
||||
public:
|
||||
Resource() : root(0) {}
|
||||
Resource() : root(NULL) {}
|
||||
Resource(const upx_byte *p) {init(p);}
|
||||
~Resource() {if (root) destroy (root,0);}
|
||||
void init(const upx_byte *);
|
||||
@@ -1046,7 +1109,7 @@ public:
|
||||
upx_byte *build();
|
||||
bool clear();
|
||||
|
||||
void dump() const {dump (root,0);}
|
||||
void dump() const { dump(root,0); }
|
||||
/*
|
||||
unsigned iname() const {return current->parent->id;}
|
||||
const upx_byte *nname() const {return current->parent->name;}
|
||||
@@ -1058,6 +1121,10 @@ public:
|
||||
|
||||
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;
|
||||
root = head = current = 0;
|
||||
dsize = ssize = 0;
|
||||
@@ -1069,7 +1136,10 @@ void Resource::check(const res_dir *node,unsigned level)
|
||||
{
|
||||
int ic = node->identr + node->namedentr;
|
||||
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++)
|
||||
if (((rde->child & 0x80000000) == 0) ^ (level == 2))
|
||||
throwCantPack("unsupported resource structure");
|
||||
@@ -1077,7 +1147,7 @@ void Resource::check(const res_dir *node,unsigned level)
|
||||
check((const res_dir*) (start + (rde->child & 0x7fffffff)),level + 1);
|
||||
}
|
||||
|
||||
Resource::upx_rnode * Resource::convert(const void *rnode,upx_rnode *parent,unsigned level)
|
||||
Resource::upx_rnode *Resource::convert(const void *rnode,upx_rnode *parent,unsigned level)
|
||||
{
|
||||
if (level == 3)
|
||||
{
|
||||
@@ -1164,16 +1234,16 @@ upx_byte *Resource::build()
|
||||
|
||||
void Resource::destroy(upx_rnode *node,unsigned level)
|
||||
{
|
||||
delete [] node->name;
|
||||
delete [] node->name; node->name = NULL;
|
||||
if (level == 3)
|
||||
return;
|
||||
const upx_rbranch *branch = (const upx_rbranch*) node;
|
||||
upx_rbranch * const branch = (upx_rbranch *) node;
|
||||
for (int ic = branch->nc; --ic >= 0; )
|
||||
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)
|
||||
{
|
||||
for (unsigned ic = 0; ic < get_le16(p); ic++)
|
||||
printf("%c",(char)p[ic * 2 + 2]);
|
||||
@@ -1183,16 +1253,17 @@ void Resource::dump(const upx_rnode *node,unsigned level) const
|
||||
{
|
||||
if (level)
|
||||
{
|
||||
printf("\t\t\t\t" + 6 - level * 2);
|
||||
for (unsigned ic = 1; ic < level; ic++)
|
||||
printf("\t\t");
|
||||
if (node->name)
|
||||
lame_print_unicode(node->name);
|
||||
else
|
||||
printf("%x",node->id);
|
||||
printf("0x%x",node->id);
|
||||
printf("\n");
|
||||
}
|
||||
if (level == 3)
|
||||
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++)
|
||||
dump(branch->children[ic],level + 1);
|
||||
}
|
||||
@@ -1204,8 +1275,9 @@ void Resource::clear(upx_byte *node,unsigned level,Interval *iv)
|
||||
else
|
||||
{
|
||||
const res_dir * const rd = (res_dir*) node;
|
||||
const unsigned n = rd->identr + rd->namedentr;
|
||||
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);
|
||||
iv->add(rd,rd->Sizeof());
|
||||
}
|
||||
@@ -1219,12 +1291,14 @@ bool Resource::clear()
|
||||
iv.flatten();
|
||||
if (iv.ivnum == 1)
|
||||
iv.clear();
|
||||
#if defined(DEBUG)
|
||||
if (opt->verbose > 3)
|
||||
iv.dump();
|
||||
#endif
|
||||
return iv.ivnum == 1;
|
||||
}
|
||||
|
||||
void PackW32Pe::processResources(Resource* res,unsigned newaddr)
|
||||
void PackW32Pe::processResources(Resource *res,unsigned newaddr)
|
||||
{
|
||||
if (IDSIZE(PEDIR_RESOURCE) == 0)
|
||||
return;
|
||||
@@ -1236,11 +1310,29 @@ void PackW32Pe::processResources(Resource* res,unsigned newaddr)
|
||||
delete [] p;
|
||||
}
|
||||
|
||||
void PackW32Pe::processResources(Resource* res)
|
||||
void PackW32Pe::processResources(Resource *res)
|
||||
{
|
||||
const unsigned vaddr = IDADDR(PEDIR_RESOURCE);
|
||||
if ((soresources = IDSIZE(PEDIR_RESOURCE)) == 0)
|
||||
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);
|
||||
|
||||
for (soresources = res->dirsize(); res->next(); soresources += 4 + res->size())
|
||||
@@ -1251,7 +1343,7 @@ void PackW32Pe::processResources(Resource* res)
|
||||
unsigned iconsin1stdir = 0;
|
||||
if (opt->w32pe.compress_icons == 2)
|
||||
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);
|
||||
|
||||
bool compress_icon = false, compress_idir = false;
|
||||
@@ -1267,25 +1359,32 @@ void PackW32Pe::processResources(Resource* res)
|
||||
{
|
||||
const unsigned rtype = res->itype();
|
||||
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)
|
||||
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)
|
||||
{
|
||||
csize += res->size();
|
||||
cnum++;
|
||||
continue;
|
||||
}
|
||||
|
||||
usize += res->size();
|
||||
unum++;
|
||||
|
||||
@@ -1294,15 +1393,15 @@ void PackW32Pe::processResources(Resource* res)
|
||||
memcpy(ores,ibuf + res->offs(),res->size());
|
||||
memset(ibuf + res->offs(),FILLVAL,res->size());
|
||||
res->newoffs() = ptr_diff(ores,oresources);
|
||||
if (rtype == 3)
|
||||
if (rtype == RT_ICON)
|
||||
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)
|
||||
{
|
||||
icondir_offset = 4 + ptr_diff(ores,oresources);
|
||||
icondir_count = get_le16 (oresources + icondir_offset);
|
||||
set_le16 (oresources + icondir_offset,1);
|
||||
icondir_count = get_le16(oresources + icondir_offset);
|
||||
set_le16(oresources + icondir_offset,1);
|
||||
}
|
||||
compress_idir = true;
|
||||
}
|
||||
@@ -1359,7 +1458,8 @@ unsigned PackW32Pe::stripDebug(unsigned overlaystart)
|
||||
LE32 size;
|
||||
char __[4]; // rva
|
||||
LE32 fpos;
|
||||
};
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
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++)
|
||||
@@ -1376,14 +1476,16 @@ unsigned PackW32Pe::stripDebug(unsigned overlaystart)
|
||||
|
||||
bool PackW32Pe::canPack()
|
||||
{
|
||||
return readFileHeader();
|
||||
if (!readFileHeader())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int PackW32Pe::buildLoader(const Filter *ft)
|
||||
{
|
||||
// prepare loader
|
||||
initLoader(nrv_loader,sizeof(nrv_loader));
|
||||
initLoader(nrv_loader, sizeof(nrv_loader), -1, 2);
|
||||
addLoader(isdll ? "PEISDLL1" : "",
|
||||
"PEMAIN01",
|
||||
icondir_count > 1 ? (icondir_count == 2 ? "PEICONS1" : "PEICONS2") : "",
|
||||
@@ -1488,9 +1590,9 @@ void PackW32Pe::pack(OutputFile *fo)
|
||||
throwCantPack("filealign < 0x200 is not yet supported");
|
||||
|
||||
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);
|
||||
ibuf.alloc(usize+xtrasize);
|
||||
ibuf.alloc(usize + xtrasize);
|
||||
|
||||
// BOUND IMPORT support. FIXME: is this ok?
|
||||
fi->seek(0,SEEK_SET);
|
||||
@@ -1500,7 +1602,7 @@ void PackW32Pe::pack(OutputFile *fo)
|
||||
|
||||
unsigned ic,jc,overlaystart = 0;
|
||||
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)
|
||||
overlaystart = ALIGN_UP(isection[ic].rawdataptr + isection[ic].size,ih.filealign);
|
||||
@@ -1512,24 +1614,27 @@ void PackW32Pe::pack(OutputFile *fo)
|
||||
holes.add(isection[ic].vaddr,isection[ic].vsize);
|
||||
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)
|
||||
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;
|
||||
if (jc > isection[ic].vsize)
|
||||
jc = isection[ic].vsize;
|
||||
if (isection[ic].vsize == 0) // hack for some tricky programs - may this break other progs?
|
||||
jc = isection[ic].vsize = isection[ic].size;
|
||||
fi->readx(ibuf + isection[ic].vaddr,jc);
|
||||
jc += isection[ic].rawdataptr;
|
||||
}
|
||||
|
||||
// check for NeoLite
|
||||
for (ic = 0; ic < 64; ic++)
|
||||
if (memcmp(ibuf + ih.entry + ic,"NeoLite",7) == 0)
|
||||
throwCantPack("file is already compressed with another packer");
|
||||
if (find(ibuf + ih.entry, 64+7, "NeoLite", 7) >= 0)
|
||||
throwCantPack("file is already compressed with another packer");
|
||||
|
||||
unsigned overlay = file_size - stripDebug(overlaystart);
|
||||
if (overlay >= (unsigned) file_size)
|
||||
@@ -1611,53 +1716,19 @@ void PackW32Pe::pack(OutputFile *fo)
|
||||
s += 4;
|
||||
ph.u_len += s;
|
||||
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
|
||||
ph.filter = 0;
|
||||
ph.u_len -= rvamin;
|
||||
// prepare filter
|
||||
Filter ft(opt->level);
|
||||
Filter ft(ph.level);
|
||||
ft.buf_len = ih.codesize;
|
||||
ft.addvalue = 0;
|
||||
// prepare other settings
|
||||
const unsigned overlap_range = 2048;
|
||||
unsigned overlapoh;
|
||||
|
||||
int strategy = -1; // try the first working filter
|
||||
if (!allow_filter)
|
||||
// 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,
|
||||
ft.addvalue = ih.codebase - rvamin;
|
||||
// compress
|
||||
int strategy = allow_filter ? 0 : -3;
|
||||
compressWithFilters(&ft, 2048, strategy,
|
||||
NULL, 0, 0, ih.codebase, rvamin);
|
||||
#endif
|
||||
|
||||
newvsize = (ph.u_len + rvamin + overlapoh + oam1) &~ oam1;
|
||||
newvsize = (ph.u_len + rvamin + ph.overlap_overhead + oam1) &~ oam1;
|
||||
if (tlsindex && ((newvsize - ph.c_len - 1024 + oam1) &~ oam1) > tlsindex + 4)
|
||||
tlsindex = 0;
|
||||
|
||||
@@ -1805,10 +1876,15 @@ void PackW32Pe::pack(OutputFile *fo)
|
||||
ODSIZE(PEDIR_RELOC) = 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;
|
||||
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
|
||||
strcpy(osection[0].name,"UPX0");
|
||||
strcpy(osection[1].name,"UPX1");
|
||||
@@ -1832,7 +1908,7 @@ void PackW32Pe::pack(OutputFile *fo)
|
||||
|
||||
osection[0].vsize = osection[1].vaddr - osection[0].vaddr;
|
||||
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[1].rawdataptr = osection[0].rawdataptr;
|
||||
@@ -1848,13 +1924,15 @@ void PackW32Pe::pack(OutputFile *fo)
|
||||
oh.database = osection[2].vaddr;
|
||||
oh.codesize = osection[1].vsize;
|
||||
oh.codebase = osection[1].vaddr;
|
||||
oh.headersize = osection[0].rawdataptr;
|
||||
// oh.headersize = osection[0].rawdataptr;
|
||||
oh.headersize = rvamin;
|
||||
|
||||
if (opt->w32pe.strip_relocs && !isdll)
|
||||
oh.flags |= RELOCS_STRIPPED;
|
||||
|
||||
//for (ic = 0; ic < oh.filealign; ic += 4)
|
||||
// set_le32(ibuf + ic,get_le32("UPX "));
|
||||
assert(oh.filealign <= ibuf.getSize());
|
||||
memset(ibuf,0,oh.filealign);
|
||||
|
||||
infoHeader("[Writing compressed file]");
|
||||
@@ -1864,7 +1942,11 @@ void PackW32Pe::pack(OutputFile *fo)
|
||||
fo->write(osection,sizeof(osection));
|
||||
// some alignment
|
||||
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);
|
||||
infoWriting("loader", fo->getBytesWritten());
|
||||
fo->write(obuf,clen);
|
||||
@@ -1896,6 +1978,9 @@ void PackW32Pe::pack(OutputFile *fo)
|
||||
printf("%-13s: relocs : %8ld bytes\n", getName(), (long) soxrelocs);
|
||||
#endif
|
||||
|
||||
// verify
|
||||
verifyOverlappingDecompression();
|
||||
|
||||
// copy the overlay
|
||||
copyOverlay(fo, overlay, &obuf);
|
||||
|
||||
@@ -1925,8 +2010,15 @@ int PackW32Pe::canUnpack()
|
||||
bool found_ph = false;
|
||||
if (memcmp(isection[0].name,"UPX",3) == 0)
|
||||
{
|
||||
found_ph = readPackHeader(1024, isection[1].rawdataptr - 64) // current version
|
||||
|| readPackHeader(1024, isection[2].rawdataptr); // old versions
|
||||
// current version
|
||||
fi->seek(isection[1].rawdataptr - 64, SEEK_SET);
|
||||
found_ph = readPackHeader(1024);
|
||||
if (!found_ph)
|
||||
{
|
||||
// old versions
|
||||
fi->seek(isection[2].rawdataptr, SEEK_SET);
|
||||
found_ph = readPackHeader(1024);
|
||||
}
|
||||
}
|
||||
if (is_packed && found_ph)
|
||||
return true;
|
||||
@@ -2112,8 +2204,8 @@ void PackW32Pe::rebuildRelocs(upx_byte *& extrainfo)
|
||||
}
|
||||
else
|
||||
memcpy (obuf + ODADDR(PEDIR_RELOC) - rvamin,oxrelocs,soxrelocs);
|
||||
delete [] oxrelocs; oxrelocs = 0;
|
||||
wrkmem.free();
|
||||
delete [] oxrelocs; oxrelocs = NULL;
|
||||
wrkmem.dealloc();
|
||||
|
||||
ODSIZE(PEDIR_RELOC) = soxrelocs;
|
||||
}
|
||||
@@ -2152,7 +2244,7 @@ void PackW32Pe::rebuildResources(upx_byte *& extrainfo)
|
||||
unsigned origoffs = get_le32(r + res.offs() - 4);
|
||||
res.newoffs() = origoffs;
|
||||
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);
|
||||
icondir_count = 0;
|
||||
@@ -2188,13 +2280,13 @@ void PackW32Pe::unpack(OutputFile *fo)
|
||||
extrainfo += sizeof (oh);
|
||||
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);
|
||||
rvamin = osection[0].vaddr;
|
||||
extrainfo += sizeof(pe_section_t) * objs;
|
||||
|
||||
// read the noncompressed section
|
||||
ibuf.free();
|
||||
ibuf.dealloc();
|
||||
ibuf.alloc(isection[2].size);
|
||||
fi->seek(isection[2].rawdataptr,SEEK_SET);
|
||||
fi->readx(ibuf,isection[2].size);
|
||||
@@ -2225,8 +2317,10 @@ void PackW32Pe::unpack(OutputFile *fo)
|
||||
ODSIZE(PEDIR_IAT) = 0;
|
||||
ODADDR(PEDIR_BOUNDIM) = 0;
|
||||
ODSIZE(PEDIR_BOUNDIM) = 0;
|
||||
//oh.headersize = osection[0].rawdataptr;
|
||||
oh.headersize = ALIGN_UP(pe_offset + sizeof(oh) + sizeof(pe_section_t) * objs, oh.filealign);
|
||||
|
||||
// oh.headersize = osection[0].rawdataptr;
|
||||
// oh.headersize = ALIGN_UP(pe_offset + sizeof(oh) + sizeof(pe_section_t) * objs, oh.filealign);
|
||||
oh.headersize = rvamin;
|
||||
oh.chksum = 0;
|
||||
|
||||
// FIXME: ih.flags is checked here because of a bug in UPX 0.92
|
||||
@@ -2240,7 +2334,7 @@ void PackW32Pe::unpack(OutputFile *fo)
|
||||
// write decompressed file
|
||||
if (fo)
|
||||
{
|
||||
ibuf.free();
|
||||
ibuf.dealloc();
|
||||
ibuf.alloc(osection[0].rawdataptr);
|
||||
memset(ibuf,0,osection[0].rawdataptr);
|
||||
infoHeader("[Writing uncompressed file]");
|
||||
@@ -2254,7 +2348,7 @@ void PackW32Pe::unpack(OutputFile *fo)
|
||||
fo->write(obuf + osection[ic].vaddr - rvamin,ALIGN_UP(osection[ic].size,oh.filealign));
|
||||
copyOverlay(fo, overlay, &obuf);
|
||||
}
|
||||
ibuf.free();
|
||||
ibuf.dealloc();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2270,6 +2364,7 @@ void PackW32Pe::unpack(OutputFile *fo)
|
||||
<offset of extra info 4>
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et
|
||||
*/
|
||||
|
||||
+30
-12
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
@@ -47,10 +47,10 @@ class PackW32Pe : public Packer
|
||||
public:
|
||||
PackW32Pe(InputFile *f);
|
||||
~PackW32Pe();
|
||||
virtual int getVersion() const { return 12; }
|
||||
virtual int getFormat() const { return UPX_F_W32_PE; }
|
||||
virtual int getVersion() const { return 13; }
|
||||
virtual int getFormat() const { return UPX_F_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 void pack(OutputFile *fo);
|
||||
@@ -61,15 +61,16 @@ public:
|
||||
|
||||
// unpacker capabilities
|
||||
virtual bool canUnpackVersion(int version) const
|
||||
{ return (version == 12); }
|
||||
{ return (version >= 12 && version <= 13); }
|
||||
|
||||
protected:
|
||||
virtual int readFileHeader();
|
||||
virtual bool testUnpackVersion(int version) const;
|
||||
|
||||
virtual int buildLoader(const Filter *ft);
|
||||
|
||||
unsigned pe_offset;
|
||||
bool isrtm;
|
||||
bool readFileHeader();
|
||||
|
||||
unsigned processImports();
|
||||
void processImports(unsigned);
|
||||
@@ -158,8 +159,12 @@ protected:
|
||||
{
|
||||
LE32 vaddr;
|
||||
LE32 size;
|
||||
} ddirs[16];
|
||||
} ih, oh;
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
struct ddirs_t ddirs[16];
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
struct pe_section_t
|
||||
{
|
||||
@@ -170,7 +175,11 @@ protected:
|
||||
LE32 rawdataptr;
|
||||
char _[12];
|
||||
LE32 flags;
|
||||
} *isection;
|
||||
}
|
||||
__attribute_packed;
|
||||
|
||||
pe_header_t ih, oh;
|
||||
pe_section_t *isection;
|
||||
|
||||
static unsigned virta2objnum (unsigned, pe_section_t *, unsigned);
|
||||
unsigned tryremove (unsigned, unsigned);
|
||||
@@ -223,6 +232,15 @@ protected:
|
||||
DLL_FLAG = 0x2000,
|
||||
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
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
+83
-73
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<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 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;
|
||||
return Packer::getDefaultCompressionMethods_le32(method, level);
|
||||
}
|
||||
|
||||
|
||||
const int *PackWcle::getFilters() const
|
||||
{
|
||||
static const int filters[] = { 0x26, 0x24, 0x14, 0x11, 0x16, 0x13,
|
||||
0x25, 0x12, 0x15, -1 };
|
||||
static const int filters[] = {
|
||||
0x26, 0x24, 0x14, 0x11, 0x16, 0x13, 0x25, 0x12, 0x15,
|
||||
-1 };
|
||||
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
|
||||
**************************************************************************/
|
||||
@@ -97,7 +127,9 @@ void PackWcle::handleStub(OutputFile *fo)
|
||||
|
||||
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);
|
||||
UNUSED(n);
|
||||
|
||||
soentries = p - ientries + 1;
|
||||
oentries = ientries;
|
||||
@@ -175,7 +208,7 @@ void PackWcle::encodeObjectTable()
|
||||
if (ic < jc)
|
||||
ic = jc;
|
||||
|
||||
unsigned csection = (ic + overlapoh + mps-1) &~ (mps-1);
|
||||
unsigned csection = (ic + ph.overlap_overhead + mps-1) &~ (mps-1);
|
||||
|
||||
OOT(0,virtual_size) = csection + mps;
|
||||
OOT(0,flags) = LEOF_READ|LEOF_EXEC|LEOF_HUGE32|LEOF_PRELOAD;
|
||||
@@ -229,25 +262,24 @@ void PackWcle::encodeFixups()
|
||||
}
|
||||
|
||||
|
||||
int PackWcle::preprocessFixups()
|
||||
void PackWcle::preprocessFixups()
|
||||
{
|
||||
unsigned ic,jc;
|
||||
int big;
|
||||
big_relocs = 0;
|
||||
|
||||
MemBuffer counts_buf((objects+2)*sizeof(unsigned));
|
||||
unsigned *counts = (unsigned *) (unsigned char *) counts_buf;
|
||||
unsigned ic,jc;
|
||||
|
||||
Array(unsigned, counts, objects+2);
|
||||
countFixups(counts);
|
||||
|
||||
for (ic = jc = 0; ic < objects; ic++)
|
||||
jc += counts[ic];
|
||||
|
||||
MemBuffer rl(jc);
|
||||
MemBuffer srf(counts[objects+0]+1);
|
||||
MemBuffer slf(counts[objects+1]+1);
|
||||
ByteArray(rl, jc);
|
||||
ByteArray(srf, counts[objects+0]+1);
|
||||
ByteArray(slf, counts[objects+1]+1);
|
||||
|
||||
upx_byte *selector_fixups = srf;
|
||||
upx_byte *selfrel_fixups = slf;
|
||||
|
||||
unsigned rc = 0;
|
||||
|
||||
upx_byte *fix = ifixups;
|
||||
@@ -255,7 +287,7 @@ int PackWcle::preprocessFixups()
|
||||
{
|
||||
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;
|
||||
|
||||
switch (*fix)
|
||||
@@ -351,7 +383,7 @@ int PackWcle::preprocessFixups()
|
||||
delete[] ifixups;
|
||||
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;
|
||||
// FIXME: this could be removed if has_extra_code = false
|
||||
// but then we'll need a flag
|
||||
@@ -364,10 +396,10 @@ int PackWcle::preprocessFixups()
|
||||
set_le32(fix,0xFFFFFFFFUL);
|
||||
fix += 4;
|
||||
|
||||
sofixups = fix-ifixups;
|
||||
return big;
|
||||
sofixups = fix - ifixups;
|
||||
}
|
||||
|
||||
|
||||
#define RESERVED 0x1000
|
||||
void PackWcle::encodeImage(const Filter *ft)
|
||||
{
|
||||
@@ -387,8 +419,10 @@ void PackWcle::encodeImage(const Filter *ft)
|
||||
// reserve RESERVED bytes for the decompressor
|
||||
if (!compress(ibuf,oimage+RESERVED))
|
||||
throwNotCompressible();
|
||||
overlapoh = findOverlapOverhead(oimage+RESERVED, 512);
|
||||
ibuf.free();
|
||||
ph.overlap_overhead = findOverlapOverhead(oimage+RESERVED, 512);
|
||||
buildLoader(ft);
|
||||
|
||||
ibuf.dealloc();
|
||||
soimage = (ph.c_len + 3) &~ 3;
|
||||
}
|
||||
|
||||
@@ -418,70 +452,43 @@ void PackWcle::pack(OutputFile *fo)
|
||||
readImage();
|
||||
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();
|
||||
|
||||
if (ih.init_ss_object != objects)
|
||||
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_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
|
||||
ifixups[sofixups++] = (unsigned char) ih.automatic_data_object;
|
||||
unsigned ic = objects*sizeof(*iobject_table);
|
||||
memcpy(ifixups+sofixups,iobject_desc,ic);
|
||||
iobject_desc.free();
|
||||
iobject_desc.dealloc();
|
||||
|
||||
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+4,ih.init_eip_offset+text_vaddr); // real entry point
|
||||
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;
|
||||
|
||||
// filter
|
||||
Filter ft(ph.level);
|
||||
tryFilters(&ft, iimage+text_vaddr, text_size, text_vaddr);
|
||||
|
||||
encodeImage(&ft);
|
||||
|
||||
// verify filter
|
||||
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();
|
||||
neweip = getLoaderSection("WCLEMAIN");
|
||||
int e_len = getLoaderSection("WCLECUTP");
|
||||
int e_len = getLoaderSectionStart("WCLECUTP");
|
||||
const unsigned d_len = lsize - e_len;
|
||||
assert(e_len > 0);
|
||||
|
||||
@@ -508,7 +515,7 @@ void PackWcle::pack(OutputFile *fo)
|
||||
|
||||
// patch loader
|
||||
ic = (OOT(0,virtual_size) - d_len) &~ 15;
|
||||
assert(ic > ((ph.u_len + overlapoh + 31) &~ 15));
|
||||
assert(ic > ((ph.u_len + ph.overlap_overhead + 31) &~ 15));
|
||||
|
||||
upx_byte * const p = oimage + soimage - d_len;
|
||||
patch_le32(p,d_len,"JMPO",ih.init_eip_offset+text_vaddr-(ic+d_len));
|
||||
@@ -531,7 +538,7 @@ void PackWcle::pack(OutputFile *fo)
|
||||
|
||||
// copy the overlay
|
||||
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;
|
||||
checkOverlay(overlay);
|
||||
copyOverlay(fo, overlay, &oimage);
|
||||
@@ -550,7 +557,7 @@ void PackWcle::decodeFixups()
|
||||
{
|
||||
upx_byte *p = oimage + soimage;
|
||||
|
||||
iimage.free();
|
||||
iimage.dealloc();
|
||||
|
||||
MemBuffer tmpbuf;
|
||||
unsigned fixupn = unoptimizeReloc32(&p,oimage,&tmpbuf,1);
|
||||
@@ -568,7 +575,7 @@ void PackWcle::decodeFixups()
|
||||
set_le32(oimage+jc,r);
|
||||
}
|
||||
set_le32(wrkmem+ic*8,0xFFFFFFFF); // end of 32-bit offset fixups
|
||||
tmpbuf.free();
|
||||
tmpbuf.dealloc();
|
||||
|
||||
// selector fixups and self-relative fixups
|
||||
const upx_byte *selector_fixups = p;
|
||||
@@ -745,8 +752,11 @@ int PackWcle::canUnpack()
|
||||
{
|
||||
if (!LeFile::readFileHeader())
|
||||
return false;
|
||||
fi->seek(exe_offset + ih.data_pages_offset, SEEK_SET);
|
||||
// FIXME: 1024 could be too large for some files
|
||||
return readPackHeader(1024, ih.data_pages_offset+exe_offset) ? 1 : -1;
|
||||
//int len = 1024;
|
||||
int len = UPX_MIN(getImageSize(), 256u);
|
||||
return readPackHeader(len) ? 1 : -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -771,7 +781,7 @@ void PackWcle::unpack(OutputFile *fo)
|
||||
handleStub(fo);
|
||||
|
||||
readObjectTable();
|
||||
iobject_desc.free();
|
||||
iobject_desc.dealloc();
|
||||
readPageMap();
|
||||
readResidentNames();
|
||||
readEntryTable();
|
||||
@@ -815,7 +825,7 @@ void PackWcle::unpack(OutputFile *fo)
|
||||
|
||||
// copy the overlay
|
||||
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;
|
||||
checkOverlay(overlay);
|
||||
copyOverlay(fo, overlay, &oimage);
|
||||
|
||||
+10
-8
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
@@ -39,10 +39,10 @@ class PackWcle : public Packer, public LeFile
|
||||
typedef Packer super;
|
||||
public:
|
||||
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 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 void pack(OutputFile *fo);
|
||||
@@ -54,6 +54,8 @@ public:
|
||||
protected:
|
||||
virtual void handleStub(OutputFile *fo);
|
||||
|
||||
virtual int buildLoader(const Filter *ft);
|
||||
|
||||
virtual void readObjectTable();
|
||||
virtual void encodeObjectTable();
|
||||
virtual void decodeObjectTable();
|
||||
@@ -66,7 +68,7 @@ protected:
|
||||
virtual void encodeEntryTable();
|
||||
virtual void decodeEntryTable();
|
||||
|
||||
virtual int preprocessFixups();
|
||||
virtual void preprocessFixups();
|
||||
virtual void encodeFixups();
|
||||
virtual void decodeFixups();
|
||||
|
||||
@@ -78,8 +80,8 @@ protected:
|
||||
// temporary copy of the object descriptors
|
||||
MemBuffer iobject_desc;
|
||||
|
||||
int big_relocs;
|
||||
bool has_extra_code;
|
||||
unsigned overlapoh;
|
||||
unsigned neweip;
|
||||
};
|
||||
|
||||
|
||||
+375
-314
File diff suppressed because it is too large
Load Diff
+39
-25
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ public:
|
||||
|
||||
public:
|
||||
// fields stored in compressed file
|
||||
unsigned magic; // UPX_MAGIC_LE32
|
||||
//enum { magic = UPX_MAGIC_LE32 };
|
||||
int version;
|
||||
int format; // executable format
|
||||
int method; // compresison method
|
||||
@@ -73,8 +73,13 @@ public:
|
||||
off_t u_file_size;
|
||||
int filter;
|
||||
int filter_cto;
|
||||
int n_mru; // FIXME: rename to filter_misc
|
||||
int header_checksum;
|
||||
|
||||
// support fields for verifying decompression
|
||||
unsigned saved_u_adler;
|
||||
unsigned saved_c_adler;
|
||||
|
||||
// info fields set by fillPackHeader()
|
||||
long buf_offset;
|
||||
|
||||
@@ -87,6 +92,9 @@ public:
|
||||
unsigned max_run_found;
|
||||
unsigned first_offset_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.
|
||||
virtual int getFormat() 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;
|
||||
|
||||
// PackMaster entries
|
||||
@@ -158,32 +166,33 @@ protected:
|
||||
virtual bool checkFinalCompressionRatio(const OutputFile *fo) const;
|
||||
|
||||
// high-level compression drivers
|
||||
void compressWithFilters(Filter *ft, unsigned *overlapoh,
|
||||
void compressWithFilters(Filter *ft,
|
||||
const unsigned overlap_range,
|
||||
int strategy = -1, const int *filters = NULL,
|
||||
int strategy = 0,
|
||||
const int *filters = NULL,
|
||||
unsigned max_offset = 0, unsigned max_match = 0,
|
||||
unsigned filter_buf_off = 0,
|
||||
unsigned compress_buf_off = 0);
|
||||
|
||||
// util for verifying overlapping decompresion
|
||||
// non-destructive test
|
||||
bool testOverlappingDecompression(const upx_bytep buf,
|
||||
unsigned overlap_overhead) const;
|
||||
virtual bool testOverlappingDecompression(const upx_bytep buf,
|
||||
unsigned overlap_overhead) const;
|
||||
// non-destructive find
|
||||
unsigned findOverlapOverhead(const upx_bytep buf,
|
||||
unsigned range = 0,
|
||||
unsigned upper_limit = ~0u) const;
|
||||
virtual unsigned findOverlapOverhead(const upx_bytep buf,
|
||||
unsigned range = 0,
|
||||
unsigned upper_limit = ~0u) const;
|
||||
// destructive decompress + verify
|
||||
void verifyOverlappingDecompression(MemBuffer *buf,
|
||||
unsigned overlap_overhead);
|
||||
virtual void verifyOverlappingDecompression();
|
||||
|
||||
|
||||
// packheader handling
|
||||
virtual int patchPackHeader(void *b, int blen);
|
||||
virtual bool readPackHeader(unsigned len, off_t seek_offset,
|
||||
upx_byte *buf=NULL);
|
||||
virtual bool getPackHeader(void *b, int blen);
|
||||
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 void tryFilters(Filter *ft, upx_byte *buf, unsigned buf_len,
|
||||
unsigned addvalue=0) const;
|
||||
@@ -191,19 +200,19 @@ protected:
|
||||
unsigned addvalue=0) const;
|
||||
virtual void optimizeFilter(Filter *, const upx_byte *, unsigned) const
|
||||
{ }
|
||||
virtual void addFilter32(int filter_id);
|
||||
virtual bool patchFilter32(void *, int, const Filter *ft);
|
||||
|
||||
// loader util
|
||||
virtual int buildLoader(const Filter *) { return getLoaderSize(); }
|
||||
virtual const upx_byte *getLoader() 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 addSection(const char *sname, const char *sdata, unsigned len);
|
||||
virtual int getLoaderSection(const char *name, int *slen=NULL) const;
|
||||
virtual int getLoaderSectionStart(const char *name) const;
|
||||
virtual void addFilter32(int filter_id);
|
||||
virtual int getLoaderSectionStart(const char *name, int *slen=NULL) const;
|
||||
virtual const char *getDecompressor() const;
|
||||
virtual const char *getIdentstr(unsigned *size, int small=-1);
|
||||
|
||||
// stub and overlay util
|
||||
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 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:
|
||||
InputFile *fi;
|
||||
@@ -239,15 +253,15 @@ protected:
|
||||
int ph_version;
|
||||
|
||||
// compression buffers
|
||||
MemBuffer ibuf; // input
|
||||
MemBuffer obuf; // output
|
||||
MemBuffer ibuf; // input
|
||||
MemBuffer obuf; // output
|
||||
|
||||
// UI handler
|
||||
UiPacker *uip;
|
||||
int ui_pass;
|
||||
int ui_total_passes;
|
||||
|
||||
private:
|
||||
protected:
|
||||
// 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
|
||||
*/
|
||||
|
||||
+50
-17
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
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)
|
||||
@@ -108,42 +108,57 @@ void PackHeader::putPackHeader(upx_bytep p)
|
||||
throwBadLoader();
|
||||
#else
|
||||
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;
|
||||
p[5] = (unsigned char) format;
|
||||
p[6] = (unsigned char) method;
|
||||
p[7] = (unsigned char) level;
|
||||
int size = 0;
|
||||
int old_chksum = 0;
|
||||
|
||||
// the new variable length header
|
||||
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)
|
||||
{
|
||||
size = 22;
|
||||
old_chksum = get_packheader_checksum(p, size - 1);
|
||||
set_le16(p+16,u_len);
|
||||
set_le16(p+18,c_len);
|
||||
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+19,c_len);
|
||||
set_le24(p+22,u_file_size);
|
||||
p[25] = (unsigned char) filter;
|
||||
}
|
||||
else if (format == UPX_F_DOS_EXEH)
|
||||
{
|
||||
throwInternalError("invalid format");
|
||||
}
|
||||
else
|
||||
{
|
||||
size = 32;
|
||||
old_chksum = get_packheader_checksum(p, size - 1);
|
||||
set_le32(p+16,u_len);
|
||||
set_le32(p+20,c_len);
|
||||
set_le32(p+24,u_file_size);
|
||||
p[28] = (unsigned char) filter;
|
||||
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
|
||||
{
|
||||
size = 32;
|
||||
old_chksum = get_packheader_checksum(p, size - 1);
|
||||
set_be32(p+8,u_len);
|
||||
set_be32(p+12,c_len);
|
||||
set_be32(p+16,u_adler);
|
||||
@@ -151,11 +166,27 @@ void PackHeader::putPackHeader(upx_bytep p)
|
||||
set_be32(p+24,u_file_size);
|
||||
p[28] = (unsigned char) filter;
|
||||
p[29] = (unsigned char) filter_cto;
|
||||
p[30] = 0;
|
||||
p[30] = (unsigned char) (n_mru ? 0 : n_mru -1);
|
||||
size = 32;
|
||||
}
|
||||
|
||||
// store header_checksum
|
||||
const int size = getPackHeaderSize();
|
||||
p[4] = (unsigned char) version;
|
||||
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);
|
||||
#endif /* UNUPX */
|
||||
}
|
||||
@@ -167,7 +198,7 @@ void PackHeader::putPackHeader(upx_bytep p)
|
||||
|
||||
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)
|
||||
return false;
|
||||
|
||||
@@ -216,6 +247,7 @@ bool PackHeader::fillPackHeader(const upx_bytep buf, int blen)
|
||||
u_file_size = get_le32(p+24);
|
||||
off_filter = 28;
|
||||
filter_cto = p[29];
|
||||
n_mru = p[30] ? 1+ p[30] : 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -227,6 +259,7 @@ bool PackHeader::fillPackHeader(const upx_bytep buf, int blen)
|
||||
u_file_size = get_be32(p+24);
|
||||
off_filter = 28;
|
||||
filter_cto = p[29];
|
||||
n_mru = p[30] ? 1+ p[30] : 0;
|
||||
}
|
||||
|
||||
if (version >= 10)
|
||||
|
||||
+47
-19
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
markus@oberhumer.com ml1050@cdata.tvnet.hu
|
||||
*/
|
||||
|
||||
|
||||
@@ -31,11 +31,13 @@
|
||||
#include "packmast.h"
|
||||
#include "packer.h"
|
||||
#include "lefile.h"
|
||||
#include "p_elf.h"
|
||||
|
||||
#include "p_com.h"
|
||||
#include "p_djgpp2.h"
|
||||
#include "p_exe.h"
|
||||
#include "p_elf.h"
|
||||
#include "p_unix.h"
|
||||
#include "p_lx_exc.h"
|
||||
#include "p_lx_elf.h"
|
||||
#include "p_lx_sep.h"
|
||||
#include "p_lx_sh.h"
|
||||
@@ -44,8 +46,10 @@
|
||||
#include "p_wcle.h"
|
||||
#include "p_tmt.h"
|
||||
#include "p_vxd.h"
|
||||
#include "p_w16ne.h"
|
||||
#include "p_w32pe.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);
|
||||
if (p->canPack())
|
||||
{
|
||||
p->updatePackHeader();
|
||||
if (opt->cmd == CMD_COMPRESS)
|
||||
p->updatePackHeader();
|
||||
f->seek(0,SEEK_SET);
|
||||
return p;
|
||||
}
|
||||
} catch (IOException&) {
|
||||
} catch (const IOException&) {
|
||||
} catch (...) {
|
||||
delete p;
|
||||
throw;
|
||||
@@ -160,6 +165,8 @@ static Packer* try_packers(InputFile *f, try_function func)
|
||||
if ((p = func(new PackVxd(f),f)) != NULL)
|
||||
return p;
|
||||
#endif
|
||||
if ((p = func(new PackW16Ne(f),f)) != NULL)
|
||||
return p;
|
||||
if ((p = func(new PackW32Pe(f),f)) != NULL)
|
||||
return p;
|
||||
}
|
||||
@@ -173,26 +180,43 @@ static Packer* try_packers(InputFile *f, try_function func)
|
||||
return p;
|
||||
|
||||
//
|
||||
// linux
|
||||
// linux kernel
|
||||
//
|
||||
#if 0
|
||||
if (opt->unix.script_name)
|
||||
{
|
||||
if ((p = func(new PackLinuxI386sep(f),f)) != NULL)
|
||||
return p;
|
||||
}
|
||||
#endif
|
||||
if ((p = func(new PackLinuxI386elf(f),f)) != NULL)
|
||||
return p;
|
||||
if ((p = func(new PackLinuxI386sh(f),f)) != NULL)
|
||||
if ((p = func(new PackVmlinuzI386(f),f)) != NULL)
|
||||
return p;
|
||||
if ((p = func(new PackBvmlinuzI386(f),f)) != NULL)
|
||||
return p;
|
||||
if ((p = func(new PackVmlinuzI386(f),f)) != NULL)
|
||||
#if 0
|
||||
if ((p = func(new PackElks8086(f),f)) != NULL)
|
||||
return p;
|
||||
#endif
|
||||
|
||||
//
|
||||
// linux
|
||||
//
|
||||
if (!opt->unix.force_execve)
|
||||
{
|
||||
#if 0
|
||||
if (opt->unix.script_name)
|
||||
{
|
||||
if ((p = func(new PackLinuxI386sep(f),f)) != NULL)
|
||||
return p;
|
||||
}
|
||||
#endif
|
||||
if ((p = func(new PackLinuxI386elf(f),f)) != NULL)
|
||||
return p;
|
||||
if ((p = func(new PackLinuxI386sh(f),f)) != NULL)
|
||||
return p;
|
||||
}
|
||||
if ((p = func(new PackLinuxI386(f),f)) != NULL)
|
||||
return p;
|
||||
|
||||
//
|
||||
// psone
|
||||
//
|
||||
if ((p = func(new PackPs1(f),f)) != NULL)
|
||||
return p;
|
||||
|
||||
//
|
||||
// .sys and .com
|
||||
//
|
||||
@@ -224,7 +248,11 @@ static Packer *getUnpacker(InputFile *f)
|
||||
|
||||
static void assertPacker(const Packer *p)
|
||||
{
|
||||
assert(p->getFormat() > 0);
|
||||
assert(p->getFormat() <= 255);
|
||||
assert(p->getVersion() >= 11);
|
||||
assert(p->getVersion() < 255);
|
||||
assert(p->getVersion() == 13);
|
||||
assert(strlen(p->getName()) <= 13);
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2000 Laszlo Molnar
|
||||
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
|
||||
@@ -21,8 +21,8 @@
|
||||
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
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
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