Compare commits

...

261 Commits

Author SHA1 Message Date
Markus F.X.J. Oberhumer 1e8214cd3f Use `volatile' to make the division relocatible.
committer: mfx <mfx> 1037059592 +0000
2002-11-12 00:06:32 +00:00
Markus F.X.J. Oberhumer 7802257700 Portability fixes.
committer: mfx <mfx> 1037058393 +0000
2002-11-11 23:46:33 +00:00
Markus F.X.J. Oberhumer 60031bed47 Disable filters if we have more than one block.
committer: mfx <mfx> 1037024125 +0000
2002-11-11 14:15:25 +00:00
Markus F.X.J. Oberhumer d7e795a731 Set blocksize in canPack().
committer: mfx <mfx> 1036984678 +0000
2002-11-11 03:17:58 +00:00
Markus F.X.J. Oberhumer c0cccd6196 Whitespace changes.
committer: mfx <mfx> 1036984538 +0000
2002-11-11 03:15:38 +00:00
Markus F.X.J. Oberhumer 6cd0d5d779 Cleanups.
committer: mfx <mfx> 1036984522 +0000
2002-11-11 03:15:22 +00:00
Markus F.X.J. Oberhumer f66d8f98c9 Changed year to 2002.
committer: mfx <mfx> 1036971635 +0000
2002-11-10 23:40:35 +00:00
Markus F.X.J. Oberhumer a94a3e9741 If testOverlappingDecompression() fails, just treat the block as
non-compressible.

committer: mfx <mfx> 1036971145 +0000
2002-11-10 23:32:25 +00:00
Markus F.X.J. Oberhumer c798242bfe Updated.
committer: mfx <mfx> 1036969636 +0000
2002-11-10 23:07:16 +00:00
Markus F.X.J. Oberhumer 80622d4037 Removed misleading "FIXME".
committer: mfx <mfx> 1036968698 +0000
2002-11-10 22:51:38 +00:00
John Reiser 5ac2eed3d9 ::unpackExtent() honors per-block filter if newer 12-byte b_info
committer: jreiser <jreiser> 1036876078 +0000
2002-11-09 21:07:58 +00:00
John Reiser 33ec757c41 AT_NUMBER grew; also fix %edx clobbered during copy of auxv
committer: jreiser <jreiser> 1036866268 +0000
2002-11-09 18:24:28 +00:00
Markus F.X.J. Oberhumer b6c84d19ab Cleanups.
committer: mfx <mfx> 1036860405 +0000
2002-11-09 16:46:45 +00:00
Markus F.X.J. Oberhumer f91849ec4b New version from Jens.
committer: mfx <mfx> 1036855572 +0000
2002-11-09 15:26:12 +00:00
Markus F.X.J. Oberhumer 46ae6e1c2a Fixed typo in comment.
committer: mfx <mfx> 1036855554 +0000
2002-11-09 15:25:54 +00:00
John Reiser 7cbf7af6e8 cleanup ui pass count
committer: jreiser <jreiser> 1036816411 +0000
2002-11-09 04:33:31 +00:00
John Reiser 7f69f5937a be gentler, use throwAlreadyPackedByUPX()
committer: jreiser <jreiser> 1036784004 +0000
2002-11-08 19:33:24 +00:00
John Reiser e0ad859eef pack1() re-allocates ibuf after setting blocksize
committer: jreiser <jreiser> 1036733697 +0000
2002-11-08 05:34:57 +00:00
Markus F.X.J. Oberhumer f5a2641ea1 Changed version number and date.
committer: mfx <mfx> 1036688381 +0000
2002-11-07 16:59:41 +00:00
Markus F.X.J. Oberhumer ccaff85870 Updated.
committer: mfx <mfx> 1036688362 +0000
2002-11-07 16:59:22 +00:00
Markus F.X.J. Oberhumer af65e40986 Added some tests to sanity check.
committer: mfx <mfx> 1035667330 +0000
2002-10-26 21:22:10 +00:00
Markus F.X.J. Oberhumer f41e3c01f4 Added be24.
committer: mfx <mfx> 1035661372 +0000
2002-10-26 19:42:52 +00:00
Markus F.X.J. Oberhumer e8b97a12a9 Updated.
committer: mfx <mfx> 1035473217 +0000
2002-10-24 15:26:57 +00:00
Markus F.X.J. Oberhumer 8744f6bd7f Added a check for unsupported coff headers.
committer: mfx <mfx> 1035473178 +0000
2002-10-24 15:26:18 +00:00
Markus F.X.J. Oberhumer 204f4eefd8 Cleanup.
committer: mfx <mfx> 1035300869 +0000
2002-10-22 15:34:29 +00:00
Markus F.X.J. Oberhumer 7af193df77 Added read() functions that take a MemBuffer as arg.
committer: mfx <mfx> 1035297017 +0000
2002-10-22 14:30:17 +00:00
Markus F.X.J. Oberhumer b082a6f1da New version from Jens.
committer: mfx <mfx> 1035190264 +0000
2002-10-21 08:51:04 +00:00
Markus F.X.J. Oberhumer ce1e5b5ae1 Updated.
committer: mfx <mfx> 1035187919 +0000
2002-10-21 08:11:59 +00:00
Markus F.X.J. Oberhumer 565360a3f2 Cleanups.
committer: mfx <mfx> 1034942507 +0000
2002-10-18 12:01:47 +00:00
John Reiser 69cec874a1 checkPatch() resets
p_lx_elf.cpp p_lx_exc.cpp p_unix.cpp

committer: jreiser <jreiser> 1034906580 +0000
2002-10-18 02:03:00 +00:00
John Reiser 66206e8dd7 %include n2e_d32.ash
Makefile l_vmlinz.asm

committer: jreiser <jreiser> 1034906454 +0000
2002-10-18 02:00:54 +00:00
John Reiser 44c1879e27 use n2e_d32.ash, n2e_d32.asy
Makefile l_lx_elf86.asm l_lx_exec86.asm l_lx_sh86.asm

committer: jreiser <jreiser> 1034834452 +0000
2002-10-17 06:00:52 +00:00
John Reiser a9bb95fefd prefer filters 0x49,0x46 until problems with 0x2Y and 0x3Y are diagnosed
committer: jreiser <jreiser> 1034794465 +0000
2002-10-16 18:54:25 +00:00
John Reiser 4ad2242e96 half-way patch (don't abort upx) for filters 0x2Y and 0x3Y; needs work
committer: jreiser <jreiser> 1034794337 +0000
2002-10-16 18:52:17 +00:00
Markus F.X.J. Oberhumer 1e1e333d61 Cleanups.
committer: mfx <mfx> 1034748563 +0000
2002-10-16 06:09:23 +00:00
Markus F.X.J. Oberhumer 81efdd41f4 Updated.
committer: mfx <mfx> 1034748530 +0000
2002-10-16 06:08:50 +00:00
Markus F.X.J. Oberhumer ac245b39d5 Re-synced `identtiny' from 1.2 branch.
committer: mfx <mfx> 1034741770 +0000
2002-10-16 04:16:10 +00:00
Markus F.X.J. Oberhumer cecfaaf63e Cleanups.
committer: mfx <mfx> 1034741718 +0000
2002-10-16 04:15:18 +00:00
Markus F.X.J. Oberhumer 8d37bb4469 Cleanups.
committer: mfx <mfx> 1034719891 +0000
2002-10-15 22:11:31 +00:00
Markus F.X.J. Oberhumer b710f2d69f Set correct header.
committer: mfx <mfx> 1034719851 +0000
2002-10-15 22:10:51 +00:00
John Reiser d96646b0e0 save 3 bytes by not clearing [AT_NULL].a_un.a_ptr
committer: jreiser <jreiser> 1034698533 +0000
2002-10-15 16:15:33 +00:00
John Reiser c069efaa1b decompress upx-1.22 linux/386 by e_entry==+0x80
committer: jreiser <jreiser> 1034698283 +0000
2002-10-15 16:11:23 +00:00
Markus F.X.J. Oberhumer 25b12eb38a Updated.
committer: mfx <mfx> 1034649809 +0000
2002-10-15 02:43:29 +00:00
Markus F.X.J. Oberhumer 6779559ba2 Default to NRV2E instead of NRV2D.
committer: mfx <mfx> 1034649545 +0000
2002-10-15 02:39:05 +00:00
Markus F.X.J. Oberhumer 4e411eab59 Enabled ALG_NRV2E.
committer: mfx <mfx> 1034637236 +0000
2002-10-14 23:13:56 +00:00
Markus F.X.J. Oberhumer 1ba9ce283b Added largefile support under Linux.
committer: mfx <mfx> 1034637175 +0000
2002-10-14 23:12:55 +00:00
Markus F.X.J. Oberhumer bd191af41b Fixed canUnpackVersion().
committer: mfx <mfx> 1034637154 +0000
2002-10-14 23:12:34 +00:00
Markus F.X.J. Oberhumer 13f4f7ffdd Added.
committer: mfx <mfx> 1034628410 +0000
2002-10-14 20:46:50 +00:00
Markus F.X.J. Oberhumer db62588d47 Build updates.
committer: mfx <mfx> 1034620929 +0000
2002-10-14 18:42:09 +00:00
Markus F.X.J. Oberhumer 17325c7939 Updated.
committer: mfx <mfx> 1034619575 +0000
2002-10-14 18:19:35 +00:00
Markus F.X.J. Oberhumer e275e7614e Whitespace changes.
committer: mfx <mfx> 1034619052 +0000
2002-10-14 18:10:52 +00:00
Markus F.X.J. Oberhumer d383b1e1a3 Docs updates.
committer: mfx <mfx> 1034618834 +0000
2002-10-14 18:07:14 +00:00
Markus F.X.J. Oberhumer 973579f462 Upgraded to latest version.
committer: mfx <mfx> 1034618509 +0000
2002-10-14 18:01:49 +00:00
Markus F.X.J. Oberhumer 05db38225a Disabled the untested filters for now.
committer: mfx <mfx> 1034617837 +0000
2002-10-14 17:50:37 +00:00
Markus F.X.J. Oberhumer 3b771656bb Fixed typo.
committer: mfx <mfx> 1034617446 +0000
2002-10-14 17:44:06 +00:00
Markus F.X.J. Oberhumer fe531960ab New ps1/exe version from Jens. Needs new asm5900-mfx5.
committer: mfx <mfx> 1034617199 +0000
2002-10-14 17:39:59 +00:00
John Reiser accbc5d809 fix parameter type nit
committer: jreiser <jreiser> 1033096360 +0000
2002-09-27 03:12:40 +00:00
Markus F.X.J. Oberhumer fa5b74b763 Added some files to `clean' rule.
committer: mfx <mfx> 1033088856 +0000
2002-09-27 01:07:36 +00:00
John Reiser 124cdfda37 new option "--ptinterp" for linux/elf386 compressing PT_INTERP file
p_lx_elf.cpp options.h main.cpp

committer: jreiser <jreiser> 1032629299 +0000
2002-09-21 17:28:19 +00:00
John Reiser 8ad3d01d81 Prepare for ability to compress PT_INTERP program.
Also save 16 bytes at cost of incompatible with glibc-2.1.1 (1999-12-29).
	fold_elf86.asm l_lx_elf.c

committer: jreiser <jreiser> 1032625240 +0000
2002-09-21 16:20:40 +00:00
Markus F.X.J. Oberhumer 448baac0f4 Updated.
committer: mfx <mfx> 1031933579 +0000
2002-09-13 16:12:59 +00:00
Markus F.X.J. Oberhumer e225d77146 Bumped version in getVersion() for all formats.
committer: mfx <mfx> 1031846916 +0000
2002-09-12 16:08:36 +00:00
Markus F.X.J. Oberhumer 74a2d9486b Initial NRV2E support. Pretty much untested.
committer: mfx <mfx> 1031841557 +0000
2002-09-12 14:39:17 +00:00
Markus F.X.J. Oberhumer 6b74aa2673 Small updates.
committer: mfx <mfx> 1031793636 +0000
2002-09-12 01:20:36 +00:00
Markus F.X.J. Oberhumer 9f4a0fedbf Updated.
committer: mfx <mfx> 1031578030 +0000
2002-09-09 13:27:10 +00:00
Markus F.X.J. Oberhumer 9b079b371d Resynced with upx 1.2 branch.
committer: mfx <mfx> 1031577224 +0000
2002-09-09 13:13:44 +00:00
Markus F.X.J. Oberhumer 1439dace83 Put into the present ;-)
committer: mfx <mfx> 1031319643 +0000
2002-09-06 13:40:43 +00:00
Markus F.X.J. Oberhumer 44a6ac4c2a Minor editing.
committer: mfx <mfx> 1031319451 +0000
2002-09-06 13:37:31 +00:00
Markus F.X.J. Oberhumer 08826398af Fixed section names.
committer: mfx <mfx> 1030883709 +0000
2002-09-01 12:35:09 +00:00
Markus F.X.J. Oberhumer 5fccfc65ec Added some assertions.
committer: mfx <mfx> 1030883678 +0000
2002-09-01 12:34:38 +00:00
Markus F.X.J. Oberhumer 91d64a8871 Removed unupx.h.
committer: mfx <mfx> 1030786943 +0000
2002-08-31 09:42:23 +00:00
Markus F.X.J. Oberhumer b9e92ba9fa Cleanups.
committer: mfx <mfx> 1030605282 +0000
2002-08-29 07:14:42 +00:00
Markus F.X.J. Oberhumer d88078aa28 Added attribute_aligned.
committer: mfx <mfx> 1030604446 +0000
2002-08-29 07:00:46 +00:00
Markus F.X.J. Oberhumer 188b952621 The name of this format is "ps/exe".
committer: mfx <mfx> 1030604353 +0000
2002-08-29 06:59:13 +00:00
Markus F.X.J. Oberhumer 804a8bb853 Some ps/exe docs from Jens, somewhat edited by me.
committer: mfx <mfx> 1030604257 +0000
2002-08-29 06:57:37 +00:00
Markus F.X.J. Oberhumer ab229ac261 CVS test.
committer: mfx <mfx> 1028264330 +0000
2002-08-02 04:58:50 +00:00
Markus F.X.J. Oberhumer ff2bbb7a31 New version from Jens.
committer: mfx <mfx> 1028263994 +0000
2002-08-02 04:53:14 +00:00
Markus F.X.J. Oberhumer c8fb0994ed Removed unused variable.
committer: mfx <mfx> 1028139040 +0000
2002-07-31 18:10:40 +00:00
Markus F.X.J. Oberhumer fd13f41294 New version from Jens.
committer: mfx <mfx> 1028128175 +0000
2002-07-31 15:09:35 +00:00
Markus F.X.J. Oberhumer 4b15d30c2a Adapted for new asm5900-mfx4.
committer: mfx <mfx> 1027601835 +0000
2002-07-25 12:57:15 +00:00
Markus F.X.J. Oberhumer 076d862ee0 Fixed syntax error.
committer: mfx <mfx> 1027598532 +0000
2002-07-25 12:02:12 +00:00
Markus F.X.J. Oberhumer f7d66c8b50 Added a check for large file size.
committer: mfx <mfx> 1027598441 +0000
2002-07-25 12:00:41 +00:00
Markus F.X.J. Oberhumer 1ef25b356c Be quiet when using `-qqq'.
committer: mfx <mfx> 1027556040 +0000
2002-07-25 00:14:00 +00:00
Markus F.X.J. Oberhumer 7e06892ad7 Correctly set the exit code.
committer: mfx <mfx> 1027556018 +0000
2002-07-25 00:13:38 +00:00
John Reiser f1ccb85658 adapt to binutils-of-the-moment
committer: jreiser <jreiser> 1027548985 +0000
2002-07-24 22:16:25 +00:00
Markus F.X.J. Oberhumer a08b3ee882 Restored revision 1.10.
committer: mfx <mfx> 1027541786 +0000
2002-07-24 20:16:26 +00:00
Markus F.X.J. Oberhumer f0fafa3ba7 Temporarily commented out some code.
committer: mfx <mfx> 1027541308 +0000
2002-07-24 20:08:28 +00:00
Markus F.X.J. Oberhumer 9c1feb24e6 Added get_xxxx_signed() functions.
committer: mfx <mfx> 1027515231 +0000
2002-07-24 12:53:51 +00:00
Markus F.X.J. Oberhumer f4aa80e6b4 Big re-sync with UPX 1.2 branch.
committer: mfx <mfx> 1026839174 +0000
2002-07-16 17:06:14 +00:00
Markus F.X.J. Oberhumer 14d22d29b1 Big re-sync with UPX 1.2 branch.
committer: mfx <mfx> 1026836316 +0000
2002-07-16 16:18:36 +00:00
Markus F.X.J. Oberhumer 666e8c2f2f Big re-sync with UPX 1.2 branch.
committer: mfx <mfx> 1026835258 +0000
2002-07-16 16:00:58 +00:00
Markus F.X.J. Oberhumer 4a462f3c9a Updated.
committer: mfx <mfx> 1026820456 +0000
2002-07-16 11:54:16 +00:00
Markus F.X.J. Oberhumer 789cfea682 Checked in psx/exe patches from Jens.
committer: mfx <mfx> 1026820270 +0000
2002-07-16 11:51:10 +00:00
John Reiser ead8daf26c beware PT_LOAD.p_filesz==0
committer: jreiser <jreiser> 1009776680 +0000
2001-12-31 05:31:20 +00:00
John Reiser 2dfb82d5b9 Linux does not grow the stack below esp, so all accesses must be >= esp.
fold_elf86.asm fold_sh86.asm l_lx_sep86.asm

committer: jreiser <jreiser> 1006463120 +0000
2001-11-22 21:05:20 +00:00
John Reiser 83bcbb8299 internal calling sequences save 37 bytes (24 when compressed)
committer: jreiser <jreiser> 994972276 +0000
2001-07-12 21:11:16 +00:00
John Reiser d85f48fb97 save 2 bytes when compressed
committer: jreiser <jreiser> 994968843 +0000
2001-07-12 20:14:03 +00:00
John Reiser e4660b8608 need to search auxv for AT_PHDR
committer: jreiser <jreiser> 994946170 +0000
2001-07-12 13:56:10 +00:00
John Reiser 96141d82f4 Spend some bytes of code in stub to eliminate wasted stack space.
(Choose between this revision and previous, according to taste.)
	fold_elf86.asm l_lx_elf.c

committer: jreiser <jreiser> 994887023 +0000
2001-07-11 21:30:23 +00:00
John Reiser ef17dc10ca Fix Elf_auxv table. upx was duplicating AT_PHDR (and others)
because Linux 2.4.5 supplies many more AT_ entries than before.
First noticed by Sebastian <scut@nb.in-berlin.de>.
	fold_elf86.asm fold_sh86.asm l_lx_sep86.asm
	l_lx_elf.c     l_lx_sh.c     l_lx_sep.c

committer: jreiser <jreiser> 994871296 +0000
2001-07-11 17:08:16 +00:00
John Reiser caca5ffa12 keep zeroed stack as clean as possible (Sebastian <scut@nb.in-berlin.de>)
l_lx_sep86.asm fold_elf86.asm

committer: jreiser <jreiser> 994702928 +0000
2001-07-09 18:22:08 +00:00
Markus F.X.J. Oberhumer e08d3858be Upgraded to ELFkickers 2.0.
committer: mfx <mfx> 987374332 +0000
2001-04-15 22:38:52 +00:00
Markus F.X.J. Oberhumer 0e063b9759 Whitespace changes.
committer: mfx <mfx> 984629032 +0000
2001-03-15 04:03:52 +00:00
Markus F.X.J. Oberhumer 6dbdef9d57 Split some string constants to avoid possible RCS keyword expansions.
committer: mfx <mfx> 983457621 +0000
2001-03-01 14:40:21 +00:00
Markus F.X.J. Oberhumer 81c58d9727 New version.
committer: mfx <mfx> 983453010 +0000
2001-03-01 13:23:30 +00:00
Markus F.X.J. Oberhumer 54701e0c46 Updated.
committer: mfx <mfx> 983452964 +0000
2001-03-01 13:22:44 +00:00
Markus F.X.J. Oberhumer 069417499f Moved the Packer's filter handling into the new source file packerf.cpp.
committer: mfx <mfx> 983452951 +0000
2001-03-01 13:22:31 +00:00
Markus F.X.J. Oberhumer 5aec670621 Catch std::bad_alloc and print a better error message in this case.
committer: mfx <mfx> 983320394 +0000
2001-02-28 00:33:14 +00:00
Markus F.X.J. Oberhumer 16e9f168b9 Updated.
committer: mfx <mfx> 983320361 +0000
2001-02-28 00:32:41 +00:00
Markus F.X.J. Oberhumer 8897c3d4cb Added `const' to catched exception.
committer: mfx <mfx> 983114224 +0000
2001-02-25 15:17:04 +00:00
Markus F.X.J. Oberhumer 48a520708b New upstream version.
committer: mfx <mfx> 983109842 +0000
2001-02-25 14:04:02 +00:00
Markus F.X.J. Oberhumer 4a142f35f5 Renamed MemBuffer::free() to dealloc() in order to better support
malloc debugging libraries like mpatrol.

committer: mfx <mfx> 983109777 +0000
2001-02-25 14:02:57 +00:00
Markus F.X.J. Oberhumer a30bb7db20 Updated.
committer: mfx <mfx> 983109539 +0000
2001-02-25 13:58:59 +00:00
Markus F.X.J. Oberhumer 61842b4bcb Updated from UPX 1.07 release.
committer: mfx <mfx> 982688397 +0000
2001-02-20 16:59:57 +00:00
Markus F.X.J. Oberhumer 0cae01772c Updated from UPX 1.07 release.
committer: mfx <mfx> 982688016 +0000
2001-02-20 16:53:36 +00:00
Markus F.X.J. Oberhumer 6a95c11cf9 Updated from UPX 1.07 release.
committer: mfx <mfx> 982687495 +0000
2001-02-20 16:44:55 +00:00
Markus F.X.J. Oberhumer 401567f852 Removed the optional `off' parameter from the [gs]et_[bl]e{16,24,32} functions.
committer: mfx <mfx> 981982200 +0000
2001-02-12 12:50:00 +00:00
Markus F.X.J. Oberhumer 475326691d Added a call to verifyOverlappingDecompression().
committer: mfx <mfx> 981981688 +0000
2001-02-12 12:41:28 +00:00
John Reiser a63b02ab69 make "upx -d" decompression backward compatible to 8-byte b_info
p_lx_elf.h p_lx_elf.cpp p_unix.cpp

committer: jreiser <jreiser> 981752402 +0000
2001-02-09 21:00:02 +00:00
John Reiser 2ff824e631 get rid of PT_DYNAMIC: not worth the space; instead, use "upx -d" then ldd
p_lx_exc.h p_lx_elf.cpp p_lx_exc.cpp p_lx_sh.cpp
	stub/l_lx_elf.c stub/l_lx_elf86.lds stub/fold_elf86.asm

committer: jreiser <jreiser> 981747384 +0000
2001-02-09 19:36:24 +00:00
John Reiser e866b2231f move b_len from PackHeader to PackUnix
packer.h p_unix.h p_unix.cpp p_lx_elf.cpp p_lx_exc.cpp

committer: jreiser <jreiser> 981741734 +0000
2001-02-09 18:02:14 +00:00
Markus F.X.J. Oberhumer 451487ef80 Added an assertion.
committer: mfx <mfx> 981702739 +0000
2001-02-09 07:12:19 +00:00
Markus F.X.J. Oberhumer 4d64bd7e66 Added UPX_VERSION_STRING4, so that the size of the stubs is not affected
by versions like "x.yy.zz beta".

committer: mfx <mfx> 981702627 +0000
2001-02-09 07:10:27 +00:00
Markus F.X.J. Oberhumer 2e21de073d Updated.
committer: mfx <mfx> 981587564 +0000
2001-02-07 23:12:44 +00:00
Markus F.X.J. Oberhumer 8675f378b6 Small cleanups - no functional changes.
committer: mfx <mfx> 981586753 +0000
2001-02-07 22:59:13 +00:00
Markus F.X.J. Oberhumer 238a369948 Cleanups.
committer: mfx <mfx> 981586521 +0000
2001-02-07 22:55:21 +00:00
Markus F.X.J. Oberhumer 7db6c25c6a Updated.
committer: mfx <mfx> 981586509 +0000
2001-02-07 22:55:09 +00:00
Markus F.X.J. Oberhumer bcbc59f04e Updated some comments.
committer: mfx <mfx> 981586421 +0000
2001-02-07 22:53:41 +00:00
Markus F.X.J. Oberhumer 1f1f03eaf4 Removed trailing whitespace.
committer: mfx <mfx> 981586094 +0000
2001-02-07 22:48:14 +00:00
Markus F.X.J. Oberhumer c9a1173698 Detabified.
committer: mfx <mfx> 981585982 +0000
2001-02-07 22:46:22 +00:00
Markus F.X.J. Oberhumer 3ba4cd5919 Avoid a compiler warning.
committer: mfx <mfx> 981585719 +0000
2001-02-07 22:41:59 +00:00
Markus F.X.J. Oberhumer 2c9f6b28f7 Added some constants and options for win32/pe resource types.
committer: mfx <mfx> 981585673 +0000
2001-02-07 22:41:13 +00:00
László Molnár 79aff4c12d Corrected tls callback handling.
Fixed a rare bug in relocation handling.
Filters need an addvalue for this format.
Experimental fix for SizeOfHeaders > 0x1000.
Check for superfluous data between sections.

committer: ml1050 <ml1050> 981241024 +0000
2001-02-03 22:57:04 +00:00
John Reiser 40fddf1715 Put upx stub loader at high end of ELF output file on linux,
and allow for block-by-block specification of filter and parameters.
	linker.cpp linker.h mem.cpp mem.h p_elf.h
	p_lx_elf.cpp p_lx_elf.h
	p_lx_exc.cpp p_lx_exc.h
	p_lx_sh.cpp  p_lx_sh.h
	p_unix.cpp p_unix.h
	packer.cpp packer.h
	stub/fold_elf86.asm stub/fold_exec86.asm stub/fold_sh86.asm
	stub/l_lx_elf.c  stub/l_lx_elf86.asm  stub/l_lx_elf86.lds
	stub/l_lx_exec.c stub/l_lx_exec86.asm stub/l_lx_exec86.lds
	stub/l_lx_sh.c   stub/l_lx_sh86.asm   stub/l_lx_sh86.lds
	stub/linux.hh

committer: jreiser <jreiser> 981084316 +0000
2001-02-02 03:25:16 +00:00
Markus F.X.J. Oberhumer 9005e50049 Check upx_adler32() arguments.
committer: mfx <mfx> 980888983 +0000
2001-01-30 21:09:43 +00:00
Markus F.X.J. Oberhumer dc7493e283 Use the overloaded upx_adler32() function.
committer: mfx <mfx> 980851465 +0000
2001-01-30 10:44:25 +00:00
Markus F.X.J. Oberhumer 8f65fc1ab7 Changed an error message.
committer: mfx <mfx> 980616295 +0000
2001-01-27 17:24:55 +00:00
Markus F.X.J. Oberhumer 3d732625a7 Cleanups.
committer: mfx <mfx> 980615091 +0000
2001-01-27 17:04:51 +00:00
Markus F.X.J. Oberhumer 5f678d10cb Some DOS updates.
committer: mfx <mfx> 980615078 +0000
2001-01-27 17:04:38 +00:00
Markus F.X.J. Oberhumer 2a55ac04ce Disable TLS callback check for now.
committer: mfx <mfx> 980615053 +0000
2001-01-27 17:04:13 +00:00
Markus F.X.J. Oberhumer 2feb5a47ac Decrease decompressor stack size a little bit.
committer: mfx <mfx> 980615022 +0000
2001-01-27 17:03:42 +00:00
Markus F.X.J. Oberhumer 27deeccdb3 Updated from 1.06 release.
committer: mfx <mfx> 980614997 +0000
2001-01-27 17:03:17 +00:00
Markus F.X.J. Oberhumer c7f12f3a74 Compute an adler32 checksum.
committer: mfx <mfx> 980609412 +0000
2001-01-27 15:30:12 +00:00
Markus F.X.J. Oberhumer 99f0f0120b Updated.
committer: mfx <mfx> 980609373 +0000
2001-01-27 15:29:33 +00:00
Markus F.X.J. Oberhumer 34070f0b93 Make fn_has_ext() case insensitive by default.
committer: mfx <mfx> 980609337 +0000
2001-01-27 15:28:57 +00:00
Markus F.X.J. Oberhumer f300b31d8d Un-documented `--stdout' option.
committer: mfx <mfx> 980606702 +0000
2001-01-27 14:45:02 +00:00
Markus F.X.J. Oberhumer bc5f9fb0a3 Don't allow `--stdout' when compressing.
committer: mfx <mfx> 980433841 +0000
2001-01-25 14:44:01 +00:00
Markus F.X.J. Oberhumer 7371c219b1 Updated from 1.05 release.
committer: mfx <mfx> 980367939 +0000
2001-01-24 20:25:39 +00:00
László Molnár d5dd445a06 refuse compressing files which have tls callbacks
committer: ml1050 <ml1050> 980113870 +0000
2001-01-21 21:51:10 +00:00
Markus F.X.J. Oberhumer b7f0187e9c Added a define to use the UPX 1.02 "blessed" stub code to avoid
problems with braindead virus scanners...

committer: mfx <mfx> 979849303 +0000
2001-01-18 20:21:43 +00:00
Markus F.X.J. Oberhumer e982426885 Made upx_adler32() an overloaded function.
committer: mfx <mfx> 979849112 +0000
2001-01-18 20:18:32 +00:00
Markus F.X.J. Oberhumer 6447666284 Support VPATH builds.
committer: mfx <mfx> 979834754 +0000
2001-01-18 16:19:14 +00:00
Markus F.X.J. Oberhumer ea4fcebf33 Made tell() const.
committer: mfx <mfx> 979831609 +0000
2001-01-18 15:26:49 +00:00
Markus F.X.J. Oberhumer 94f7d49522 Make the stubs compile again.
committer: mfx <mfx> 979829197 +0000
2001-01-18 14:46:37 +00:00
Markus F.X.J. Oberhumer bbf2938719 Avoid an app.pl warning.
committer: mfx <mfx> 979828878 +0000
2001-01-18 14:41:18 +00:00
John Reiser df9db96bd1 filters for unix(linux)
Modified Files:
	filteri.cpp filter/ctojr.h linker.cpp linker.h mem.cpp mem.h
	p_lx_elf.cpp p_lx_elf.h
	p_lx_exc.cpp p_lx_exc.h
	p_lx_sh.cpp  p_lx_sh.h
	p_unix.cpp packer.cpp packer.h packhead.cpp
	stub/Makefile    stub/macros.ash
	stub/l_lx_elf.c  stub/l_lx_elf86.asm  stub/l_lx_elf86.lds
	stub/l_lx_exec.c stub/l_lx_exec86.asm stub/l_lx_exec86.lds
	                 stub/l_lx_sh86.asm   stub/l_lx_sh86.lds
Added Files:
	filter/ctok.h
	stub/fold_elf86.asm stub/fold_exec86.asm stub/fold_sh86.asm

committer: jreiser <jreiser> 979796725 +0000
2001-01-18 05:45:25 +00:00
Markus F.X.J. Oberhumer 4d45677160 Updated.
committer: mfx <mfx> 979756847 +0000
2001-01-17 18:40:47 +00:00
Markus F.X.J. Oberhumer 2981596fc3 Clarified a comment.
committer: mfx <mfx> 979756736 +0000
2001-01-17 18:38:56 +00:00
Markus F.X.J. Oberhumer ecce4d6578 Reset patch order in writePackHeader().
committer: mfx <mfx> 979756690 +0000
2001-01-17 18:38:10 +00:00
Markus F.X.J. Oberhumer bf52b5eb06 Small PackHeader update.
committer: mfx <mfx> 979756656 +0000
2001-01-17 18:37:36 +00:00
Markus F.X.J. Oberhumer d8baf6d1e8 Added PackUnix::writePackHeader().
committer: mfx <mfx> 979754833 +0000
2001-01-17 18:07:13 +00:00
Markus F.X.J. Oberhumer 4322931d97 Added UPX_MAGIC2_LE32 as an additional magic number for the original
packheader as stored in the stubs.

committer: mfx <mfx> 979754722 +0000
2001-01-17 18:05:22 +00:00
Markus F.X.J. Oberhumer ad4bf703f0 Added some comments.
committer: mfx <mfx> 979748824 +0000
2001-01-17 16:27:04 +00:00
Markus F.X.J. Oberhumer 342679b6d3 Small cleanups.
committer: mfx <mfx> 979748793 +0000
2001-01-17 16:26:33 +00:00
Markus F.X.J. Oberhumer 4a52be76fe Removed nop() macro.
committer: mfx <mfx> 979746778 +0000
2001-01-17 15:52:58 +00:00
Markus F.X.J. Oberhumer afc55d76e7 New version of the UNUSED() macro.
committer: mfx <mfx> 979744725 +0000
2001-01-17 15:18:45 +00:00
Markus F.X.J. Oberhumer 9e53f19b02 New upstream version.
committer: mfx <mfx> 979654847 +0000
2001-01-16 14:20:47 +00:00
Markus F.X.J. Oberhumer 8614bca405 Updated.
committer: mfx <mfx> 979237786 +0000
2001-01-11 18:29:46 +00:00
Markus F.X.J. Oberhumer 5f3bdaeebe Support VPATH builds.
committer: mfx <mfx> 979143860 +0000
2001-01-10 16:24:20 +00:00
Markus F.X.J. Oberhumer fd81cd2ae0 Support VPATH builds.
committer: mfx <mfx> 979143221 +0000
2001-01-10 16:13:41 +00:00
Markus F.X.J. Oberhumer bc6599ae51 Added a simple delta filter.
committer: mfx <mfx> 978980129 +0000
2001-01-08 18:55:29 +00:00
Markus F.X.J. Oberhumer 6c2c174926 Added a simple delta filter.
committer: mfx <mfx> 978979757 +0000
2001-01-08 18:49:17 +00:00
Markus F.X.J. Oberhumer 9205d0be65 New version.
committer: mfx <mfx> 978973564 +0000
2001-01-08 17:06:04 +00:00
Markus F.X.J. Oberhumer 199e274cac Added a simple delta filter.
committer: mfx <mfx> 978973515 +0000
2001-01-08 17:05:15 +00:00
John Reiser c9a36d51c4 refine pseudo-sections
committer: jreiser <jreiser> 978901287 +0000
2001-01-07 21:01:27 +00:00
John Reiser 7bffc86777 prepare for selective buildLoader
committer: jreiser <jreiser> 978897024 +0000
2001-01-07 19:50:24 +00:00
John Reiser ce1b58d293 filters for linux/elf386;
filter.cpp filter.h p_lx_elf.cpp p_lx_elf.h filter/ctojr.h
	stub/l_lx_elf.c stub/l_lx_elf86.asm

committer: jreiser <jreiser> 978846586 +0000
2001-01-07 05:49:46 +00:00
John Reiser 4d2b35c9ee debugging
committer: jreiser <jreiser> 978826747 +0000
2001-01-07 00:19:07 +00:00
Markus F.X.J. Oberhumer 47168972da Added class BeLinker.
committer: mfx <mfx> 978797683 +0000
2001-01-06 16:14:43 +00:00
Markus F.X.J. Oberhumer dee289e2d9 Comments updated.
committer: mfx <mfx> 978795901 +0000
2001-01-06 15:45:01 +00:00
Markus F.X.J. Oberhumer 1fc7c7898b Updated.
committer: mfx <mfx> 978795803 +0000
2001-01-06 15:43:23 +00:00
Markus F.X.J. Oberhumer dfc8a0d548 Renamed ctjo to ctoj, and ctjor to ctojr.
committer: mfx <mfx> 978792885 +0000
2001-01-06 14:54:45 +00:00
Markus F.X.J. Oberhumer daa0fe353b Added util function getcto().
committer: mfx <mfx> 978792675 +0000
2001-01-06 14:51:15 +00:00
John Reiser 766b3edeee Avoid static storage. Also keep as many destinations as possible,
and keep them together on the wheel during "cold cache" startup.

committer: jreiser <jreiser> 978729012 +0000
2001-01-05 21:10:12 +00:00
Markus F.X.J. Oberhumer 8e90fd0b63 Updated.
committer: mfx <mfx> 978721813 +0000
2001-01-05 19:10:13 +00:00
Markus F.X.J. Oberhumer 9a00a9027d Cleanups.
committer: mfx <mfx> 978706067 +0000
2001-01-05 14:47:47 +00:00
Markus F.X.J. Oberhumer e2a45c8f97 Added static bool Filter::isValidFilter(int).
committer: mfx <mfx> 978705885 +0000
2001-01-05 14:44:45 +00:00
Markus F.X.J. Oberhumer ee69861fb5 Added some comments.
committer: mfx <mfx> 978705469 +0000
2001-01-05 14:37:49 +00:00
John Reiser 5b97d3ee09 Filter for lru recoding of "call trick" destinations.
filteri.cpp filter/ctjor.h

committer: jreiser <jreiser> 978670287 +0000
2001-01-05 04:51:27 +00:00
Markus F.X.J. Oberhumer 38ab492030 Added preliminary unpacking support.
committer: mfx <mfx> 978638046 +0000
2001-01-04 19:54:06 +00:00
Markus F.X.J. Oberhumer 266d992017 Cleanups.
committer: mfx <mfx> 978636047 +0000
2001-01-04 19:20:47 +00:00
Markus F.X.J. Oberhumer 0979848bdc Added experimental app_68k.pl.
committer: mfx <mfx> 978635857 +0000
2001-01-04 19:17:37 +00:00
Markus F.X.J. Oberhumer 3d371be0e5 Updated.
committer: mfx <mfx> 978626197 +0000
2001-01-04 16:36:37 +00:00
Markus F.X.J. Oberhumer f96955b9f0 Updated my email address.
committer: mfx <mfx> 978625825 +0000
2001-01-04 16:30:25 +00:00
Markus F.X.J. Oberhumer 794d048bf2 Moved the actual filter implementations into the new filter directory.
committer: mfx <mfx> 978622245 +0000
2001-01-04 15:30:45 +00:00
Markus F.X.J. Oberhumer 595afd8964 Updated.
committer: mfx <mfx> 978564648 +0000
2001-01-03 23:30:48 +00:00
Markus F.X.J. Oberhumer da8fadb203 Updated.
committer: mfx <mfx> 978563845 +0000
2001-01-03 23:17:25 +00:00
Markus F.X.J. Oberhumer ca7c07e817 Added some debug print statements.
committer: mfx <mfx> 978563773 +0000
2001-01-03 23:16:13 +00:00
Markus F.X.J. Oberhumer bf95f93cad Added a number of filters. Some of them could be useful for dos/exe.
committer: mfx <mfx> 978563749 +0000
2001-01-03 23:15:49 +00:00
Markus F.X.J. Oberhumer 7766b08f08 Cleanups.
committer: mfx <mfx> 978563615 +0000
2001-01-03 23:13:35 +00:00
Markus F.X.J. Oberhumer 823ac11eb3 Added option `--no-filter'.
committer: mfx <mfx> 978559146 +0000
2001-01-03 21:59:06 +00:00
Markus F.X.J. Oberhumer c5e61413a4 Small cleanups.
committer: mfx <mfx> 978539758 +0000
2001-01-03 16:35:58 +00:00
Markus F.X.J. Oberhumer df4726eb95 Removed Packer::addSection().
committer: mfx <mfx> 978539327 +0000
2001-01-03 16:28:47 +00:00
Markus F.X.J. Oberhumer 25a6da5638 dos/com and dos/sys: only add the `sbb bp,bp' section to the stub
if it is needed.

committer: mfx <mfx> 978538864 +0000
2001-01-03 16:21:04 +00:00
Markus F.X.J. Oberhumer 5ddec963d0 Better kernel decompression.
committer: mfx <mfx> 978531885 +0000
2001-01-03 14:24:45 +00:00
Markus F.X.J. Oberhumer 597143df7f Added some more header checks.
committer: mfx <mfx> 978531825 +0000
2001-01-03 14:23:45 +00:00
Markus F.X.J. Oberhumer 572082ac2b Implemented Packer::verifyOverlappingDecompression().
committer: mfx <mfx> 978465508 +0000
2001-01-02 19:58:28 +00:00
Markus F.X.J. Oberhumer d328e834b1 Documentation updates.
committer: mfx <mfx> 978450814 +0000
2001-01-02 15:53:34 +00:00
Markus F.X.J. Oberhumer aa540f85fa Big merge of my working tree: Added options `--all-methods', new
Packer::getCompressionMethods(), improved Packer::compressWithFilters().

committer: mfx <mfx> 978449945 +0000
2001-01-02 15:39:05 +00:00
Markus F.X.J. Oberhumer 1084d86063 Some more cleanups.
committer: mfx <mfx> 978191791 +0000
2000-12-30 15:56:31 +00:00
Markus F.X.J. Oberhumer a43d93512d Updated.
committer: mfx <mfx> 978190991 +0000
2000-12-30 15:43:11 +00:00
Markus F.X.J. Oberhumer a8177201ef Added new field PackHeader::overlap_overhead.
committer: mfx <mfx> 978190533 +0000
2000-12-30 15:35:33 +00:00
Markus F.X.J. Oberhumer 85bebf0b43 Major rewrite: added buildLoader() and fillExeHeader().
committer: mfx <mfx> 978189850 +0000
2000-12-30 15:24:10 +00:00
Markus F.X.J. Oberhumer f36feee0dc Added a framework for the win16/ne format, so that it's easier for someone
to actually contribute that.

committer: mfx <mfx> 978183080 +0000
2000-12-30 13:31:20 +00:00
Markus F.X.J. Oberhumer c0bbc2216e Always call buildLoader() directly after compress().
committer: mfx <mfx> 978181874 +0000
2000-12-30 13:11:14 +00:00
Markus F.X.J. Oberhumer 8ce23f15e8 Updated.
committer: mfx <mfx> 978180979 +0000
2000-12-30 12:56:19 +00:00
Markus F.X.J. Oberhumer 0b01be7b29 Consistency cleanups.
committer: mfx <mfx> 978180862 +0000
2000-12-30 12:54:22 +00:00
Markus F.X.J. Oberhumer ceebd3518b Implemented buildLoader(), so that we can add compressWithFilters().
committer: mfx <mfx> 978180698 +0000
2000-12-30 12:51:38 +00:00
Markus F.X.J. Oberhumer a9249c6335 Implemented compressWithFilters().
committer: mfx <mfx> 978180632 +0000
2000-12-30 12:50:32 +00:00
Markus F.X.J. Oberhumer dc22e6f158 Changed a comment.
committer: mfx <mfx> 978108487 +0000
2000-12-29 16:48:07 +00:00
Markus F.X.J. Oberhumer 1c7a34b367 Updated.
committer: mfx <mfx> 978108464 +0000
2000-12-29 16:47:44 +00:00
Markus F.X.J. Oberhumer 526ae77b08 Whitespace changes.
committer: mfx <mfx> 978108441 +0000
2000-12-29 16:47:21 +00:00
Markus F.X.J. Oberhumer 82698fb4b0 Enabled compressWithFilters(). Added some assertions.
committer: mfx <mfx> 978108380 +0000
2000-12-29 16:46:20 +00:00
Markus F.X.J. Oberhumer 63ead04054 Documented `--all-filters'.
committer: mfx <mfx> 978108298 +0000
2000-12-29 16:44:58 +00:00
Markus F.X.J. Oberhumer 5727461522 Updated.
committer: mfx <mfx> 978101535 +0000
2000-12-29 14:52:15 +00:00
Markus F.X.J. Oberhumer cd4292dd55 Completely updated the TODO list.
committer: mfx <mfx> 978101036 +0000
2000-12-29 14:43:56 +00:00
Markus F.X.J. Oberhumer 11ee8627b8 Improved some ELF header checks.
committer: mfx <mfx> 978099239 +0000
2000-12-29 14:13:59 +00:00
Markus F.X.J. Oberhumer 65ad79d727 Updated.
committer: mfx <mfx> 978093031 +0000
2000-12-29 12:30:31 +00:00
Markus F.X.J. Oberhumer 85920ea8b1 Use the new macro COMPILE_TIME_ASSERT() instead of several assert().
committer: mfx <mfx> 978092937 +0000
2000-12-29 12:28:57 +00:00
Markus F.X.J. Oberhumer f4d2287e57 Added some experimental test code.
committer: mfx <mfx> 978092868 +0000
2000-12-29 12:27:48 +00:00
Markus F.X.J. Oberhumer 8a77a477df Do not use the screen code when running under Windows NT.
committer: mfx <mfx> 978092789 +0000
2000-12-29 12:26:29 +00:00
Markus F.X.J. Oberhumer 5a497e2dac Added a framework for the elks/8086 format. Completely non-functional at the moment.
committer: mfx <mfx> 978092698 +0000
2000-12-29 12:24:58 +00:00
Markus F.X.J. Oberhumer 7d5042012b Avoid a compiler warning.
committer: mfx <mfx> 978092515 +0000
2000-12-29 12:21:55 +00:00
Markus F.X.J. Oberhumer d2625d8607 *** empty log message ***
committer: mfx <mfx> 977924664 +0000
2000-12-27 13:44:24 +00:00
Markus F.X.J. Oberhumer c3ec6b73e5 Use UPX_MAGIC_LE32 instead of PackHeader::magic.
committer: mfx <mfx> 977922670 +0000
2000-12-27 13:11:10 +00:00
Markus F.X.J. Oberhumer 0ffe40c621 Updated.
committer: mfx <mfx> 977489915 +0000
2000-12-22 12:58:35 +00:00
Markus F.X.J. Oberhumer 537f9111ae Documented `--force-execve'.
committer: mfx <mfx> 977488831 +0000
2000-12-22 12:40:31 +00:00
Markus F.X.J. Oberhumer d168d85650 Some ELF related cleanups.
committer: mfx <mfx> 977488389 +0000
2000-12-22 12:33:09 +00:00
Markus F.X.J. Oberhumer dbbc47a334 Added option `--force-execve' which forces the use of the generic
linux/386 format.

committer: mfx <mfx> 977486503 +0000
2000-12-22 12:01:43 +00:00
Markus F.X.J. Oberhumer 47760c37fc Updated.
committer: mfx <mfx> 977431602 +0000
2000-12-21 20:46:42 +00:00
Markus F.X.J. Oberhumer 9fc785199a Only #include "version.h" in files that actually need it.
committer: mfx <mfx> 977430123 +0000
2000-12-21 20:22:03 +00:00
Markus F.X.J. Oberhumer f4f70634a1 Made PackHeader::magic a constant.
committer: mfx <mfx> 977428640 +0000
2000-12-21 19:57:20 +00:00
Markus F.X.J. Oberhumer 046df6da76 Added Packer::checkAlreadyPacked().
committer: mfx <mfx> 977427988 +0000
2000-12-21 19:46:28 +00:00
Markus F.X.J. Oberhumer facca7b891 Added test for alreadyPacked().
committer: mfx <mfx> 977426670 +0000
2000-12-21 19:24:30 +00:00
Markus F.X.J. Oberhumer a254e81ba9 Oops.
committer: mfx <mfx> 977426094 +0000
2000-12-21 19:14:54 +00:00
Markus F.X.J. Oberhumer 09eb201b76 *** empty log message ***
committer: mfx <mfx> 977425661 +0000
2000-12-21 19:07:41 +00:00
Markus F.X.J. Oberhumer b0226b54bd Finally we use automated dependencies.
committer: mfx <mfx> 977424557 +0000
2000-12-21 18:49:17 +00:00
Markus F.X.J. Oberhumer 1d948c839d Moved the generic linux/386 format into the new p_lx_exc.{h,cpp} files.
committer: mfx <mfx> 977423460 +0000
2000-12-21 18:31:00 +00:00
Markus F.X.J. Oberhumer 5d74b7252d Cleaned up the use of upx_compress(), use delete[] where needed.
committer: mfx <mfx> 977422374 +0000
2000-12-21 18:12:54 +00:00
Markus F.X.J. Oberhumer e787805b81 Extended gzip signature to 3 bytes.
committer: mfx <mfx> 977403238 +0000
2000-12-21 12:53:58 +00:00
Markus F.X.J. Oberhumer 166d91ac48 Added some assertions.
committer: mfx <mfx> 977395014 +0000
2000-12-21 10:36:54 +00:00
Markus F.X.J. Oberhumer 2bb2124356 readFileHeader() now returns 0 on error.
committer: mfx <mfx> 977394998 +0000
2000-12-21 10:36:38 +00:00
Markus F.X.J. Oberhumer 29ae1b7231 Updated.
committer: mfx <mfx> 977393157 +0000
2000-12-21 10:05:57 +00:00
Markus F.X.J. Oberhumer 06dc67da49 Added some more checks to canPack(), throw an exception in case
of crippled ELF headers.

committer: mfx <mfx> 977393134 +0000
2000-12-21 10:05:34 +00:00
Markus F.X.J. Oberhumer 42fe803a39 Cleaned up some canPack() checks.
committer: mfx <mfx> 977393067 +0000
2000-12-21 10:04:27 +00:00
John Reiser 1dcaedab30 sys_size is only 16 bits and can wrap around
committer: jreiser <jreiser> 977374512 +0000
2000-12-21 04:55:12 +00:00
Markus F.X.J. Oberhumer adcb357242 Updated.
committer: mfx <mfx> 977342634 +0000
2000-12-20 20:03:54 +00:00
Markus F.X.J. Oberhumer 1e1a078808 Cleaned up Packer::readPackHeader().
committer: mfx <mfx> 977342419 +0000
2000-12-20 20:00:19 +00:00
Markus F.X.J. Oberhumer 7d652fa42b Increased precision of get_ratio() and swapped parameters.
committer: mfx <mfx> 977342070 +0000
2000-12-20 19:54:30 +00:00
László Molnár a42e72094a fixed CUTPOINT related stuff
committer: ml1050 <ml1050> 977333745 +0000
2000-12-20 17:35:45 +00:00
Markus F.X.J. Oberhumer 97ff8042b4 Added a note that this file is completely out of date. We really should
start a new TODO list.

committer: mfx <mfx> 977314954 +0000
2000-12-20 12:22:34 +00:00
173 changed files with 13587 additions and 5607 deletions
-1
View File
@@ -1,5 +1,4 @@
.cvsignore
.mfxcvsup
ChangeLog.cvs*
build
maint
+2 -3
View File
@@ -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:
+12 -6
View File
@@ -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
+79 -4
View File
@@ -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
+19 -14
View File
@@ -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:
+16 -19
View File
@@ -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
View File
@@ -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
View File
@@ -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
+2 -3
View File
@@ -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
.___.. .
+91 -166
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+7
View File
@@ -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
View File
@@ -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
+16
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 */
/*
+226
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
*/
+21 -51
View File
@@ -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
*/
+25 -52
View File
@@ -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
*/
+343
View File
@@ -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
*/
+169
View File
@@ -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
*/
+173
View File
@@ -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
*/
+75
View File
@@ -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
*/
+87
View File
@@ -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
*/
+122
View File
@@ -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
*/
+122
View File
@@ -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
*/
+122
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
}
+13 -8
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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[]
};
+470
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
*/
+67
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+39 -25
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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