Compare commits
1802 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 33cdcb0e82 | |||
| ec870a5aeb | |||
| 0653bb5a72 | |||
| 43b6ff29e3 | |||
| a444a8a704 | |||
| 3fa18c1799 | |||
| 19147963b9 | |||
| 5056215a1f | |||
| 340b7614e2 | |||
| 8a1bd67a20 | |||
| a094df7b55 | |||
| cc893dfc11 | |||
| 8ef17da082 | |||
| 7993e619cd | |||
| 1ab8d5fb3f | |||
| 213ac3ac73 | |||
| 0a8876443a | |||
| f37a3bb9bb | |||
| 2632342f44 | |||
| 8efcf6f099 | |||
| 58343fc78d | |||
| 6c41a4c9c8 | |||
| 334be287fc | |||
| aa050e0001 | |||
| cc994326a0 | |||
| 58de07629e | |||
| 9f830e0c41 | |||
| c52d302f07 | |||
| 44049ecf30 | |||
| e1b5904196 | |||
| 88e692791a | |||
| f00667ad7d | |||
| 696d0eec64 | |||
| 513b00a30e | |||
| 0cb0dbf6d8 | |||
| 9f00515da4 | |||
| 72f31787f6 | |||
| cd686cb1d9 | |||
| d9657e9831 | |||
| 72f3e9b25a | |||
| 811b15a5b3 | |||
| ab00825f37 | |||
| e86d9179aa | |||
| 26d8e9c4c5 | |||
| 5f3ebc8a7f | |||
| 425b1b44bc | |||
| 39442e6282 | |||
| 99575e1010 | |||
| 64aa7540e2 | |||
| 3ff5dbd179 | |||
| e25d04fb12 | |||
| dd1d5a92d2 | |||
| c6e0aad40b | |||
| 99b795ceaa | |||
| 33dc60df26 | |||
| 619aeb54ff | |||
| 77ba43328b | |||
| 01a30752c7 | |||
| e56b748435 | |||
| bb4cbdff44 | |||
| 0b47e474a7 | |||
| 8e85680eb4 | |||
| fefce0d5c4 | |||
| 0ac3cb2329 | |||
| 708ab1dcd7 | |||
| 9b87ddb621 | |||
| 5dc4eb4b03 | |||
| a203c72281 | |||
| 6cf85cee6e | |||
| 1eb6a40fdd | |||
| 1bed77e4d3 | |||
| f2a68023fa | |||
| 8ccffc40e3 | |||
| dd8c1d0441 | |||
| f9f28ff176 | |||
| 3649041195 | |||
| c23c7a9379 | |||
| 9934e33b99 | |||
| 9e75fdda66 | |||
| d873a26f41 | |||
| 91aa5b55ab | |||
| 3f460a76ce | |||
| 7256ea3b32 | |||
| 4cdf77e16f | |||
| d89813e911 | |||
| 7c57b10cae | |||
| 8d1a98e03b | |||
| 65a2da4b40 | |||
| 02f6786b2a | |||
| 9da4f7a6dc | |||
| 510505a85c | |||
| 741cb3a136 | |||
| 9f5d67e27c | |||
| 93c6496ba8 | |||
| 779b648c5f | |||
| 9d5e06232d | |||
| b221c44466 | |||
| 665296f7cf | |||
| 39778d5f47 | |||
| 0af9bbb623 | |||
| fdec47a83d | |||
| 7ff913bbd2 | |||
| 94775bef9f | |||
| 3cf102334f | |||
| 627e733a30 | |||
| d31b80da5b | |||
| eb231b65f3 | |||
| 59e3b1f98d | |||
| 8b174bb272 | |||
| 4199a44bef | |||
| 777392c0fe | |||
| ede1fec5e7 | |||
| 16de3e78a5 | |||
| d7508d8c09 | |||
| 2a136c1c1d | |||
| 2578102be9 | |||
| dadee7acfb | |||
| 28f0bb4e11 | |||
| 824c8a8efb | |||
| 37f27a1262 | |||
| 2b8a7a492a | |||
| db56bbb11b | |||
| 82d26f04a4 | |||
| 5045f7eb42 | |||
| 82a6ccac4d | |||
| 2d74298001 | |||
| ce21254ed2 | |||
| 874250fe49 | |||
| c8a3acbba8 | |||
| 81e11987a2 | |||
| 668cefec2f | |||
| 212bc04257 | |||
| db401fd05e | |||
| bebe72481c | |||
| 2b9e83256d | |||
| 5763518cce | |||
| 3e4c5bab72 | |||
| bce109ab54 | |||
| 69ca635c4c | |||
| e0bf460993 | |||
| 29762a8a96 | |||
| c7ef08dc2d | |||
| 50a6698715 | |||
| 7dd2cdea1e | |||
| af87f7f2bf | |||
| 295889023f | |||
| feef2e38cf | |||
| 80d30aab32 | |||
| e910a9dc3e | |||
| 504224696c | |||
| e2acd666df | |||
| e5c0d998b7 | |||
| 63f6fef964 | |||
| 983eb6d676 | |||
| 98fedef1a1 | |||
| 75a769759d | |||
| 2354b01bad | |||
| c331b9f1e2 | |||
| afeaeeddec | |||
| ab7ef9f511 | |||
| d3ad6d25d8 | |||
| 2e29f9fa5f | |||
| 5d9f71bb13 | |||
| 82ed25bb44 | |||
| f57393c0e8 | |||
| b54cced19c | |||
| 60a0544314 | |||
| 283c1cf931 | |||
| fff53efc05 | |||
| 07d368adca | |||
| 13276d93fa | |||
| 79b1b1a586 | |||
| 2f083f3e56 | |||
| 73b0b4db9d | |||
| ca0e614b56 | |||
| 72613d06a5 | |||
| 48ad5513ff | |||
| 201d9f1346 | |||
| 1e8f1f49d0 | |||
| 65707900bc | |||
| 39c5be43aa | |||
| c4437cb293 | |||
| e2b86a49db | |||
| 8fe83be87f | |||
| 17167d4905 | |||
| 05ff7e35a1 | |||
| f67cec4752 | |||
| fd4882abcf | |||
| 0f42579e68 | |||
| 7398d8f68f | |||
| ec33109b22 | |||
| 2cfa4c1eb7 | |||
| a13b4d10d9 | |||
| 36e94e58d0 | |||
| d0a52bd483 | |||
| 38a1d3179b | |||
| 0d639d6386 | |||
| 4256057c27 | |||
| b720b47c12 | |||
| 55e4a4f086 | |||
| b4cb9f8b2f | |||
| 63298ebd6d | |||
| 73c816e468 | |||
| 0492e650ef | |||
| b8b94ee89e | |||
| 81176716d5 | |||
| 26e7ae00e9 | |||
| c75d7a685d | |||
| 4318cc22ee | |||
| 575cb720c6 | |||
| 5db34fbf92 | |||
| 7cfef2f6bf | |||
| 4603f1df4b | |||
| c69fcfff9d | |||
| 70f14101ed | |||
| a9803459ed | |||
| 43034e8e92 | |||
| ef547034f6 | |||
| e87fc60391 | |||
| 45e6e73d85 | |||
| be30c26dbb | |||
| 79e9b0762c | |||
| a9a806c418 | |||
| c7d8b6fed1 | |||
| a723efd225 | |||
| cf429dfce4 | |||
| 3fcd64a0c0 | |||
| 83cb38022b | |||
| 93c04d1f66 | |||
| 3c47898cf4 | |||
| 61e1366122 | |||
| a20636fd63 | |||
| aa8cdca0a9 | |||
| 6931a3aa70 | |||
| d001a63bce | |||
| 0d3377f48b | |||
| aeb04d97c8 | |||
| eb68ab91cd | |||
| ee242ba987 | |||
| 44a53736ff | |||
| 1b21fef081 | |||
| 5f9c50cd3e | |||
| 793d8c1d2e | |||
| 81f868a0c6 | |||
| dadbbbdc64 | |||
| bfd2153f2b | |||
| 077793fa5e | |||
| acad3c3000 | |||
| 3b4627e17e | |||
| 05976ee1a7 | |||
| c1311c78a3 | |||
| 717150b7f3 | |||
| a68c62d938 | |||
| c11f8a569a | |||
| 03436d2415 | |||
| 4ae75375e0 | |||
| 2721ef0636 | |||
| 7a232cb330 | |||
| 52f19ae330 | |||
| 275477f914 | |||
| 2ed6755d5d | |||
| 78c555b4a6 | |||
| a127125707 | |||
| f853f91c5b | |||
| e7ca5c54ff | |||
| 663d6b466b | |||
| 0e2a9de2b2 | |||
| 34df0d6ef1 | |||
| 540164849b | |||
| 252143d0bb | |||
| 480ab51650 | |||
| 972c76eb42 | |||
| e5aeea9ed2 | |||
| f204670008 | |||
| 651155c64d | |||
| 660aee6d22 | |||
| a646231630 | |||
| 1050de5171 | |||
| b7a5b9437a | |||
| 620955a724 | |||
| 2e64a277f8 | |||
| ea567a8b14 | |||
| be23f93ee6 | |||
| fcdf0e92c1 | |||
| 2d6987252e | |||
| 4a9c46253e | |||
| 5bcf9dd8af | |||
| 284adb203f | |||
| adafa841f7 | |||
| fdc5d25d03 | |||
| 294a7077de | |||
| 990d0ec543 | |||
| bb90c4dff4 | |||
| 00e3d992e8 | |||
| 937bfa4e49 | |||
| 1d9c211eed | |||
| 76ddf6b8da | |||
| 7f1f29b0d8 | |||
| 222471744f | |||
| cc100be26e | |||
| 966b571b7c | |||
| f3e710394a | |||
| bfd1f1fbfa | |||
| a09146b5e0 | |||
| bbf2b08f48 | |||
| e2dbc661f1 | |||
| 7626e09f66 | |||
| 248a6980cf | |||
| f956bfc797 | |||
| 6da79783ea | |||
| 22329e0ab2 | |||
| a94b0329c9 | |||
| be8601f8cc | |||
| bd441e83ae | |||
| 02bd9cc403 | |||
| c9f6a3583c | |||
| 076aaf829a | |||
| 85f0c5a445 | |||
| d5263a56ce | |||
| ef5b55b4d1 | |||
| d65e65b2b1 | |||
| 6aa641e5aa | |||
| 504839951a | |||
| d55746f62d | |||
| 144010295e | |||
| 181c752488 | |||
| bd4aca5c12 | |||
| ad6d73c875 | |||
| c5cc83d424 | |||
| fe949bdf67 | |||
| 766fe466d6 | |||
| 333a288248 | |||
| 613df414ed | |||
| be050693f2 | |||
| bf957f435e | |||
| 3a6f688265 | |||
| 1084a7896c | |||
| 9ea2b31541 | |||
| 09da986742 | |||
| cb70a5fef5 | |||
| 4fa6a6aeef | |||
| ab31e8dde9 | |||
| 53d7b5449f | |||
| d33a34f016 | |||
| f6ff5a2805 | |||
| 1518e5bc98 | |||
| 78f48d65d5 | |||
| b81ec224b7 | |||
| 4be6cfebcd | |||
| 98973dd8b9 | |||
| 1218b6ff2a | |||
| ba5c77c9e5 | |||
| cbaedffce2 | |||
| cb60603950 | |||
| 0a69e7803b | |||
| baa9090198 | |||
| e78a08b8fc | |||
| 7e5e6012df | |||
| 0a1d24d1d9 | |||
| 35555bfb8a | |||
| c9cb42df40 | |||
| 2be03028f4 | |||
| 214dd0a522 | |||
| 182e0796df | |||
| fb844a8ed1 | |||
| 6be3e747ca | |||
| 23f63e4196 | |||
| fd6837b267 | |||
| 1c29f921e0 | |||
| 1ab6e01de2 | |||
| 801618740c | |||
| 2469563b26 | |||
| 00139caf43 | |||
| 21d102c84f | |||
| f17d9967c2 | |||
| 0569ef37ba | |||
| 984334c9a1 | |||
| 34a25e61c7 | |||
| ed3f45953e | |||
| 80de11bc5b | |||
| c9fe84c9aa | |||
| 5f98bb0ab0 | |||
| d86d5314ba | |||
| 700c8730cf | |||
| b4429e1a42 | |||
| a8fa3ca5cf | |||
| 9aef7b0d6f | |||
| 2575eef3c0 | |||
| 8236276a90 | |||
| fdc68812c5 | |||
| 9db6d18d11 | |||
| f962afe146 | |||
| adcd569852 | |||
| d045b7f223 | |||
| 57cb6a7530 | |||
| baa1ed9be3 | |||
| 16af6e1a29 | |||
| 0af8998be6 | |||
| c32f517fa5 | |||
| 9131d5216f | |||
| fb14a7991d | |||
| ff53862dab | |||
| 49245a20c5 | |||
| 13bc031163 | |||
| 0c18c1c35c | |||
| 63dc19ce25 | |||
| 6871c2fc0a | |||
| 4ae3a8b2b0 | |||
| f2e562b5de | |||
| f7e2266c3f | |||
| 361a3056cb | |||
| ca0437556d | |||
| 51899957a9 | |||
| 7b0b760d78 | |||
| 4f5866b5a7 | |||
| a6b5033cf1 | |||
| a6296ecd67 | |||
| bb1df15958 | |||
| 249431f45f | |||
| cbe129795e | |||
| 2a135e245b | |||
| 05a0b3557a | |||
| c7cfe8b608 | |||
| 8d3e1d28a7 | |||
| 7841e15583 | |||
| dd164fbc86 | |||
| 23fe02e84a | |||
| 94e72238f2 | |||
| 8f7ac520eb | |||
| bd193201b2 | |||
| 8ced672d24 | |||
| f218812858 | |||
| 8a7b980fc0 | |||
| 385c9877f8 | |||
| 10df93536e | |||
| 6cad27896f | |||
| 052392d97b | |||
| ce6b5a0688 | |||
| 1879185e42 | |||
| a928a08f9d | |||
| 1805cb6857 | |||
| 6ce625b535 | |||
| 4702f12818 | |||
| 4f3054f07d | |||
| 0d7bd52e21 | |||
| c3466f579c | |||
| 7c105d7af5 | |||
| 924b229afb | |||
| 890d66ecf0 | |||
| 143049922b | |||
| e6ccef2cf1 | |||
| be61e9f584 | |||
| 89d0fda9fa | |||
| 6a85bab5da | |||
| c1a55b063e | |||
| 77c914bce5 | |||
| cc60f03b2e | |||
| cc9ccdbbd1 | |||
| 9dfc8f573c | |||
| 4e2fdb464a | |||
| 73b854874e | |||
| 0016512df1 | |||
| 527139978a | |||
| 47bc68fa6b | |||
| 972b670a64 | |||
| d7c416f243 | |||
| 3ace7a0468 | |||
| d305023f5e | |||
| 963392a5ae | |||
| 2f453acf5d | |||
| 4ae1576726 | |||
| 17bd0b3248 | |||
| a1ad1aee99 | |||
| a817ed0692 | |||
| 828a6cf07b | |||
| 962c35aa08 | |||
| b327645e64 | |||
| e1b42616a2 | |||
| f96638c42a | |||
| 6272152dfe | |||
| 030a200c08 | |||
| 994da63b4d | |||
| 2315bff280 | |||
| 98dddf93d8 | |||
| fd2939e18d | |||
| 80c27e0822 | |||
| b463f24eda | |||
| 2a849444db | |||
| 69e106c0c5 | |||
| 926481dace | |||
| a3b2cde58d | |||
| 30f37d2cc6 | |||
| c4d61dd9fe | |||
| 210870f840 | |||
| 4cb4bd38eb | |||
| 58c6d19f7c | |||
| f99ae94747 | |||
| 6868ca7953 | |||
| 87a5a4ef32 | |||
| c67a5d677c | |||
| 1ce6f0e6f4 | |||
| 740b4ff865 | |||
| 1059f62566 | |||
| df3193c1ee | |||
| 67860e3704 | |||
| 35fbb1ecb6 | |||
| c63a71ad42 | |||
| f33645f739 | |||
| d7ba31cab8 | |||
| 342b1b7d6c | |||
| 936013f60c | |||
| fdf2eddc73 | |||
| 4409753014 | |||
| 9172ae3d19 | |||
| e2f60adc95 | |||
| 1bb93d4fce | |||
| eb90eab632 | |||
| 0f4975fd7f | |||
| b5b1f06a11 | |||
| 86f8eb0930 | |||
| 91ad0e7572 | |||
| b034ee98fe | |||
| ded07f8781 | |||
| 849bdd87e1 | |||
| 643e48efd7 | |||
| 92f072cf70 | |||
| 95bf2e2e41 | |||
| 6a6c6d84eb | |||
| 08a689c81e | |||
| d1174385ef | |||
| cb5f590e10 | |||
| 5ed9c66ed9 | |||
| b8f52d14f4 | |||
| 5d295c24f0 | |||
| 8be9da8280 | |||
| 819c33fee2 | |||
| 75a2cc4ecb | |||
| e2833cf303 | |||
| 801de73dbe | |||
| 6a53c0b3d4 | |||
| 58b122d97d | |||
| 276b748aa6 | |||
| 23570097cf | |||
| 62a07df45e | |||
| 593a69ce25 | |||
| c33603e324 | |||
| 29fa358077 | |||
| 49766388bc | |||
| f23267bddd | |||
| 4484acf9d6 | |||
| 47ddace96a | |||
| 8aadbcd786 | |||
| 517bc9db0b | |||
| 16bfa7b846 | |||
| 570b2d0e88 | |||
| 2653a0749a | |||
| 3de0008543 | |||
| d4e2d7e8a8 | |||
| a9c08c6f52 | |||
| c2aa5c35f7 | |||
| 423f1a8758 | |||
| cc5f684e33 | |||
| b6646d319a | |||
| 3667fa4e44 | |||
| d1c80154f6 | |||
| 3c2bfc742e | |||
| d60fef753f | |||
| 70ed2d0d03 | |||
| 716d203a78 | |||
| 9719a7dd56 | |||
| c097233bf3 | |||
| 69a583281f | |||
| 8e90c9af2b | |||
| a784284b7f | |||
| 0509edf08d | |||
| 7ca20f424f | |||
| b74d51c2a8 | |||
| 58061cd121 | |||
| b8f6be5389 | |||
| 7c766b3313 | |||
| 91b81b587b | |||
| 780a4347b8 | |||
| 606ad08dd1 | |||
| 75c31dff1d | |||
| 473b90419f | |||
| f88b85e126 | |||
| b122f8e9d0 | |||
| cb8b1595a1 | |||
| 1bee919276 | |||
| 78b1da5c00 | |||
| bb8239ccda | |||
| 2a594ad0a7 | |||
| b05073550c | |||
| 37d6a34e58 | |||
| 4f0cba9bb6 | |||
| 4d1c754af9 | |||
| c1cfde21d7 | |||
| bb1f9cdecd | |||
| b259b0ca28 | |||
| 0051dfc84f | |||
| 9f294e6ce5 | |||
| 153ea8be03 | |||
| f3f7f97f8d | |||
| 9bb6854e64 | |||
| 4bba1e6cb7 | |||
| 597e8fe407 | |||
| 556c541ffb | |||
| 5963f18f7c | |||
| 0dac6b7be3 | |||
| 296ede780b | |||
| faaa19331a | |||
| 88cb5886f3 | |||
| 2fcc3f86c0 | |||
| 9362fde9eb | |||
| 56f4d781c1 | |||
| 7a3637ff5a | |||
| 2923c0968e | |||
| 98cfe99d65 | |||
| bdd97fe0b2 | |||
| 6b500bc83b | |||
| 92a12a2ec1 | |||
| 04d79040f9 | |||
| 3201ddc680 | |||
| 2f06de54c5 | |||
| 6489ec9bba | |||
| 1a5ba22fe7 | |||
| 8f9713ed53 | |||
| 90eb68b3b9 | |||
| 95fcbcb4f2 | |||
| b97688d119 | |||
| 5ea3627cab | |||
| d9288213ec | |||
| 614c86fb7d | |||
| 9f651ee40f | |||
| 774c8c3fd4 | |||
| b711d2f750 | |||
| 8a793d5942 | |||
| 99f52c60ed | |||
| 2c2e108301 | |||
| 563165e6ae | |||
| f1a31b4793 | |||
| 5e9b6bd69d | |||
| 9b990c4eae | |||
| 7a625a449a | |||
| c2b62359d5 | |||
| 6722e8972e | |||
| fefe7a3452 | |||
| 90a1322929 | |||
| d698eb69e2 | |||
| 0ef00e9b82 | |||
| 95cedb6640 | |||
| d736da4208 | |||
| be83788666 | |||
| 5a28a51abc | |||
| 8a84df752c | |||
| 85f53b210d | |||
| 5d13c6cd01 | |||
| 98a0d381e9 | |||
| e1d20fd0b5 | |||
| d1035ecd8f | |||
| 0e651facdd | |||
| 9fdddfc332 | |||
| 7d2913709c | |||
| 3623199e8d | |||
| e4b23f7a47 | |||
| f056ecdcd5 | |||
| 857a03a074 | |||
| a34deee4f5 | |||
| fc9c8ae482 | |||
| 08c63f06eb | |||
| bbff510ef1 | |||
| f747435952 | |||
| e6edad8f46 | |||
| 05e44b9644 | |||
| 16bb7ab841 | |||
| 9248f02557 | |||
| 9485a56af1 | |||
| 021c8db58a | |||
| 8ab180edf8 | |||
| ab35b685d4 | |||
| 86745721ee | |||
| c34fe09a79 | |||
| 1fa9ff2c05 | |||
| e8ef0cf63f | |||
| 8c84efb8fb | |||
| f3a7620ae8 | |||
| c7969ed5a5 | |||
| 900926c0ed | |||
| df94f4288a | |||
| 969efe687d | |||
| ee3f1292d0 | |||
| cacb239040 | |||
| 28d1789783 | |||
| 633eb98e34 | |||
| 4854c03096 | |||
| e853119c77 | |||
| 161a58bafb | |||
| f5fd94e815 | |||
| edde6210f1 | |||
| 507e19945e | |||
| 4a35bf32ea | |||
| e04bf9e4bc | |||
| c384d224c0 | |||
| 35427f998e | |||
| 1174da2bc3 | |||
| 11e8a47030 | |||
| 8c4e9bcf0d | |||
| 9dfd624901 | |||
| 79e65503a9 | |||
| 59f18b9d9f | |||
| fb3699fb89 | |||
| 9d2d59b5d2 | |||
| aefb2fa3c3 | |||
| e8aa80f904 | |||
| 990988f920 | |||
| 576d9a4e7e | |||
| 1d462ee424 | |||
| c9b09555c4 | |||
| 860b5bf967 | |||
| 5063480a38 | |||
| 3400ae9dbe | |||
| 3385264eb2 | |||
| 34646f1c6a | |||
| 50aa63a5a0 | |||
| 64557bee43 | |||
| 7c21c4513e | |||
| c6d6378005 | |||
| 4f6979967d | |||
| e633c51b50 | |||
| 143f0accef | |||
| b413f3da26 | |||
| 6eafa552bb | |||
| 7a0514d9b4 | |||
| 7e7565299e | |||
| ed34a089c6 | |||
| d14a2c5282 | |||
| f014406b65 | |||
| 58771ecca6 | |||
| 5d9dcb634b | |||
| 19c2c1edcf | |||
| 0430e7931e | |||
| bb8e607442 | |||
| e61ada944d | |||
| 46730315e3 | |||
| 4869142034 | |||
| 8e42e17bbf | |||
| 38c8b84a26 | |||
| c652626a37 | |||
| 06f6e47ebf | |||
| 403b180b1d | |||
| ee008acfbd | |||
| d149092ac0 | |||
| eafa136c69 | |||
| 402c885987 | |||
| 5e7e0508b9 | |||
| ff1d5fb794 | |||
| ad3f63b5c4 | |||
| a3e51e6dee | |||
| c1b9c79f54 | |||
| e0bc040b0a | |||
| 85eb4c7537 | |||
| 1f929d47d0 | |||
| 608662d73b | |||
| 7841d23e77 | |||
| b72dda4ada | |||
| c59c8a1ea2 | |||
| 1522293be0 | |||
| b37bc99330 | |||
| 7f905724b1 | |||
| 2bf5bb1625 | |||
| 08d3376740 | |||
| 7bace76176 | |||
| ef336dbcc6 | |||
| ca7217e717 | |||
| 3931cb7871 | |||
| 9e8de4abe5 | |||
| 26be845563 | |||
| 2f11a629fa | |||
| a295437e11 | |||
| 04597fb804 | |||
| f2f002409b | |||
| 509de877ca | |||
| 63aea4a7dc | |||
| 6470c748db | |||
| 25a6429e6a | |||
| 4fa1c2a97e | |||
| 9ad39d77cc | |||
| 92527126a8 | |||
| 02b4a4c974 | |||
| ede570be21 | |||
| 08627e9df5 | |||
| 6d9f3adc86 | |||
| 96433b4e39 | |||
| f4947cc2ae | |||
| 7b554d4f72 | |||
| 5b54544438 | |||
| ef78d23494 | |||
| ef8a7f330d | |||
| b72e0f3060 | |||
| 2a0bab938b | |||
| cd637629c4 | |||
| b9adfd801d | |||
| 69355514c9 | |||
| 33dc947c21 | |||
| 6de021d8d8 | |||
| 9be86621bf | |||
| a7a0876298 | |||
| 31b42345c3 | |||
| 1b172e729e | |||
| 3bf387a2d4 | |||
| 9f20bbb046 | |||
| 82af555974 | |||
| 50638b5213 | |||
| 650df95b72 | |||
| b2115a4162 | |||
| d67bf16a08 | |||
| a4c9b64224 | |||
| 8f572e5fe6 | |||
| e58873044b | |||
| 8ada92a69f | |||
| 3c8ed5c000 | |||
| c127d5b64a | |||
| 2d3bd0809a | |||
| eef955a9dd | |||
| e59ce39dc6 | |||
| 62815f5c3c | |||
| f496010273 | |||
| 143c4e3322 | |||
| e7f1e99a5e | |||
| 140a031515 | |||
| b7c91941b8 | |||
| 33f0b6da67 | |||
| ee18fe9bba | |||
| a51330cf07 | |||
| a67aed2744 | |||
| d979e19315 | |||
| 4c74d16795 | |||
| 6e541a432f | |||
| d8f47e248a | |||
| d1a869496b | |||
| f42a37555d | |||
| d9e019bd87 | |||
| ce194fa5d8 | |||
| b5bdf57636 | |||
| a3a81ce7c6 | |||
| 61f347401c | |||
| d985a4c250 | |||
| d31947e1f0 | |||
| e4659b7d7c | |||
| 8827a534db | |||
| ddf48b45a5 | |||
| 8eabb9b02f | |||
| 8a195a0b35 | |||
| 955206aaf0 | |||
| 082dd7d5ee | |||
| 90714cf624 | |||
| 61798d33f0 | |||
| 6e2a41cb26 | |||
| 515897e180 | |||
| fe4a8f33b1 | |||
| 304d848f53 | |||
| b5f738abf3 | |||
| 7ebed06393 | |||
| 2e56fe82bb | |||
| 32019c61aa | |||
| f7ffae565c | |||
| cd11bb1606 | |||
| 24c924d668 | |||
| 9be94e4b58 | |||
| 15e9d8c99d | |||
| 391f511094 | |||
| 5b53c11a6b | |||
| 9df4b6ea24 | |||
| a440564ba4 | |||
| 9583cfcc93 | |||
| c4a921283a | |||
| 4e05f087f9 | |||
| 40b506d2e0 | |||
| 263f384810 | |||
| d80c145a18 | |||
| 8848fe35f6 | |||
| 7a681bd20d | |||
| ed31fb184b | |||
| 360b94dd6c | |||
| 8524e73f59 | |||
| 940514e5ca | |||
| a4e47625ac | |||
| 7c16872a6e | |||
| 994c3c3552 | |||
| c34f496600 | |||
| 8bca8629be | |||
| 85fdd579d6 | |||
| e88d2ff88c | |||
| bdf08baebd | |||
| 3dcdd25177 | |||
| 491e8640b2 | |||
| b23b7ef85e | |||
| b167374f13 | |||
| cd1f6e733f | |||
| d3fc7687b8 | |||
| 17a83d58da | |||
| 18a8e1b6d6 | |||
| 2c23cbb359 | |||
| cdd58cf757 | |||
| a0df325659 | |||
| a59005e836 | |||
| 5da6a27e6b | |||
| ef97af71e3 | |||
| 6ed67f4532 | |||
| 1278d663b4 | |||
| 0395c7b407 | |||
| df3d15ffb3 | |||
| 6f673310d2 | |||
| 978c3eca23 | |||
| 20bc848bd6 | |||
| ce7f1292dc | |||
| d97ff8bb40 | |||
| 8a9b46d82f | |||
| 12e5703541 | |||
| 1b87fc2ee6 | |||
| ebd0c780a1 | |||
| bd976cd562 | |||
| 0e511c3e07 | |||
| 300d489408 | |||
| 024d081167 | |||
| 348173d3f1 | |||
| 23e3814f8a | |||
| b818e2c4b8 | |||
| 6adb3dc142 | |||
| 0e154cc759 | |||
| 9dce8d9bce | |||
| 0aa3b9c487 | |||
| dc7ab3ed30 | |||
| 254259b354 | |||
| 9651c70efd | |||
| 5840190ed5 | |||
| a807b88694 | |||
| 0db82e09e9 | |||
| e5865f171a | |||
| 166d198dcb | |||
| 445795f2ec | |||
| 6be4a87dac | |||
| 17c47053d6 | |||
| b4e18f7521 | |||
| fbe4d287c7 | |||
| 543fa3ae79 | |||
| 7cf855413c | |||
| f5d65dc0bc | |||
| 2f6211a1d9 | |||
| 513a57330a | |||
| 715ddf0620 | |||
| 6bb31e276e | |||
| b10f1df49f | |||
| f999519b13 | |||
| aedbf02830 | |||
| bd5479b250 | |||
| 9d14715652 | |||
| 72156fcf1b | |||
| 1c6eab00d1 | |||
| f9738c5b55 | |||
| 3b63083619 | |||
| d5d7d8bc84 | |||
| f26118cf5a | |||
| 5d6c4b475c | |||
| 2c4ef392f6 | |||
| 2a128fe772 | |||
| bb7d3ca3a1 | |||
| a2bdba7eda | |||
| e8aabc9980 | |||
| 9f554a14fd | |||
| 68a2b91ccb | |||
| 4089cc6e6f | |||
| 4e8848eeca | |||
| 8c6133c115 | |||
| 483db31acd | |||
| 35dae3dab7 | |||
| 8232aedf78 | |||
| d30a0a2e67 | |||
| d913fe508f | |||
| 4029903301 | |||
| 5db7e826d3 | |||
| 7f3e7da7c7 | |||
| 93cefde8fc | |||
| 02e7981e10 | |||
| 0ecec10af0 | |||
| 00b8cba987 | |||
| 8486bff918 | |||
| 5305eb5b8a | |||
| 377a3bb7de | |||
| 5a47e8d2c6 | |||
| 71f4cd7c85 | |||
| f7751684af | |||
| 59df1d39b2 | |||
| 7e5933e6a0 | |||
| 2cefd34bb7 | |||
| eac891dc3a | |||
| abd3599408 | |||
| 1bcd259c00 | |||
| c4e835266c | |||
| 685953f6a5 | |||
| 03fffbc724 | |||
| e1a8c932ee | |||
| 1aa2a6b054 | |||
| 1ad96c9c81 | |||
| f69199909f | |||
| d063e77040 | |||
| bf3ddeb1eb | |||
| fc261ad8cd | |||
| 90fc018295 | |||
| cdc01d9a69 | |||
| da7e76c07d | |||
| ba9118aa58 | |||
| fdce705e55 | |||
| 81268e7064 | |||
| f502f41359 | |||
| 34c9cfb6b0 | |||
| 6da1790c46 | |||
| d333c940da | |||
| c940d2906f | |||
| ac4b51ba85 | |||
| ea7a1ad2c7 | |||
| 45ddd6a68d | |||
| acd99364e0 | |||
| 14710dea55 | |||
| 5d3be8da1d | |||
| 3026821f9f | |||
| fba51dabd0 | |||
| c4da5e81fa | |||
| bc80d81432 | |||
| 67797efead | |||
| c7cb036536 | |||
| 0ccbc5f139 | |||
| 2a6bbcaf8f | |||
| d46a8438ba | |||
| cc9d19da19 | |||
| 6e6aa6fd6d | |||
| 61652a2989 | |||
| edd7503607 | |||
| c9d6dab401 | |||
| d303038bcb | |||
| 0a0e7c3b7c | |||
| 0b4ac35bc9 | |||
| c51864ca39 | |||
| a1cabd5a68 | |||
| 9c1bc99d7a | |||
| c05fedcb76 | |||
| e11beeae4b | |||
| 4749e0d71e | |||
| 1c01b77a71 | |||
| 1dd8ad3685 | |||
| d6f6350b54 | |||
| 4f3b85e604 | |||
| efd5bc24b0 | |||
| a1d5dfa1ac | |||
| 597c2ba180 | |||
| 2c2fb1b70b | |||
| fc1287659a | |||
| 1a76630594 | |||
| 322f682d32 | |||
| 0e329336fc | |||
| b33bdabbb6 | |||
| 27d30121ab | |||
| 345278f309 | |||
| 4953e77161 | |||
| 8d61e037f9 | |||
| 33a51e69bf | |||
| d5dd9bbf24 | |||
| 8772e52513 | |||
| 9e1631ad4f | |||
| 134b829d59 | |||
| 3df7d26101 | |||
| cf56086f06 | |||
| a72aca4379 | |||
| edb0b7519a | |||
| 3a3248c88c | |||
| 3f14b9dab7 | |||
| b1c07c22ce | |||
| 3b2c411274 | |||
| e418af1ccd | |||
| 7dc004acb3 | |||
| 2635472896 | |||
| 5c0340f9ae | |||
| c2c970ee33 | |||
| b52dabe091 | |||
| 3fa2db8d6f | |||
| 1e7950f671 | |||
| 8fde05191a | |||
| 2557de6c4e | |||
| 44328aee76 | |||
| f606b5879b | |||
| 83607119df | |||
| 9b86e68268 | |||
| d688a05ac7 | |||
| 97e975b4f6 | |||
| 9dd0e3ce4f | |||
| ca2293f6d3 | |||
| 0cd1ef0c7a | |||
| b0207ce524 | |||
| fab0c3b09d | |||
| 8b35dd3358 | |||
| cadcbb27eb | |||
| 297d44c614 | |||
| 22178f2224 | |||
| 554f8a376c | |||
| 4157affbd7 | |||
| 4b991203df | |||
| 38a265741c | |||
| 56eb02280f | |||
| ed900b0476 | |||
| 42206364e5 | |||
| 82d9bb8f51 | |||
| 923a9d3f9b | |||
| ae7660068b | |||
| f466c1d764 | |||
| 6e76f8ef3a | |||
| b3a8d02caf | |||
| 022ba32c1a | |||
| 8f5e89c900 | |||
| d335d7bafd | |||
| 1f51ef7df6 | |||
| ec082ee023 | |||
| a6bc271e0d | |||
| 791fd9199e | |||
| 9e8baf1914 | |||
| 64b7080532 | |||
| 8fd5479f32 | |||
| 04eb9c02c3 | |||
| 07b41b9bc3 | |||
| 8ebadfafe9 | |||
| 3283896e4b | |||
| b444bcf418 | |||
| 13034577fc | |||
| 9feefc2e7f | |||
| a5393e985d | |||
| e3fe0dc89b | |||
| 42d49e9d50 | |||
| 06eb244800 | |||
| 870cdfa51f | |||
| 93787c74ee | |||
| 945323fe15 | |||
| 5e41e69b27 | |||
| 9d14185f7d | |||
| 0f74162551 | |||
| 00b1ff1ff6 | |||
| 977024ea94 | |||
| 3534ed21d7 | |||
| ee093e5232 | |||
| 807ab8d19f | |||
| 81f3ff098f | |||
| 85a5759afb | |||
| 490e7a56a5 | |||
| e41c475671 | |||
| b0841268bd | |||
| b9b3b67b95 | |||
| 0d57d2cfe3 | |||
| 32de5d0d7f | |||
| 51eab2a4b7 | |||
| 93cf170253 | |||
| f7554374ab | |||
| b4870f62c9 | |||
| f1d713ebf6 | |||
| 4134a512b9 | |||
| cf998f945c | |||
| a7386238dd | |||
| 6b39d122a6 | |||
| a0582c5380 | |||
| 1f37112969 | |||
| 361958db76 | |||
| 8bc7880b19 | |||
| ceddf29586 | |||
| 3fc78e21bc | |||
| 48e00b371c | |||
| aee52d3880 | |||
| bd54499537 | |||
| e6da9e8d1a | |||
| 156ca03b67 | |||
| 3f4419b177 | |||
| 676f860d7d | |||
| 5ce93ae0c7 | |||
| 43231826b9 | |||
| 899b393fcc | |||
| 5c3e02d2f0 | |||
| a29064107e | |||
| 4cdc969801 | |||
| 68159d457e | |||
| daafc29d2b | |||
| 3c786acf2b | |||
| 53c3817d4d | |||
| 9109254488 | |||
| df19f0d5ec | |||
| 093362e479 | |||
| 7826a3652b | |||
| c27b7e52e1 | |||
| 6f79cbb2a6 | |||
| 6f33929f91 | |||
| 2e8b649195 | |||
| 3841be7e20 | |||
| 2c28521283 | |||
| 1c735cc204 | |||
| f0b13ae8e4 | |||
| b1a2f8fec0 | |||
| 83828aa8a3 | |||
| 4eb81b4d66 | |||
| 96d9968db5 | |||
| 2781e37ec0 | |||
| 6d61e773b5 | |||
| c5171114d1 | |||
| 0ca0a832de | |||
| aef54a4bfd | |||
| 4c473acfec | |||
| 0de41e97ac | |||
| 0e52ab3f90 | |||
| 797679b42c | |||
| 1bc8b6f46e | |||
| f322b580ff | |||
| 2b2f33e3f5 | |||
| ce29cd2fad | |||
| 0d5843f44e | |||
| e36e8e3b33 | |||
| e251a1ca19 | |||
| 4aedb00e43 | |||
| 10a0469221 | |||
| d3419acada | |||
| 65ea4117ca | |||
| 8b0101dcab | |||
| 188f67cfca | |||
| a89f4bd4b8 | |||
| 053c9dc0e1 | |||
| 493d9f1b9d | |||
| e28793f128 | |||
| ea2bddf245 | |||
| 763b3c05af | |||
| 473cfb54be | |||
| a7fd742c17 | |||
| b66ba140cb | |||
| 242f606a29 | |||
| 60a1214d7e | |||
| 189ab8c8e8 | |||
| 3765ca4e92 | |||
| df87d76070 | |||
| 8fbf0b406b | |||
| 633073803f | |||
| 104da198d3 | |||
| b3121e4534 | |||
| 3bb654cc85 | |||
| d2830db94d | |||
| ad6914b938 | |||
| 57ba965b93 | |||
| 544ec21fc2 | |||
| 1bb0fa1809 | |||
| ffa0efc898 | |||
| af6b4b8c27 | |||
| 3f7c1f966b | |||
| 535515f296 | |||
| 7af6c4b10e | |||
| 2076bef95b | |||
| 48ce1f1814 | |||
| 5151c8a505 | |||
| 44248f19b5 | |||
| 8d433f2580 | |||
| 272fe5488c | |||
| c97765de14 | |||
| 7acf150ac5 | |||
| 077bbdfc78 | |||
| 2fb38ce13a | |||
| 22dc183f25 | |||
| 3c492c3fc7 | |||
| d71db2978e | |||
| e4723e0bad | |||
| dc56c4e530 | |||
| 9579a51a8b | |||
| 71f897ebf5 | |||
| 09d9f71ae9 | |||
| c678ccdfb1 | |||
| bbbebe343b | |||
| 033cb4f0c2 | |||
| d750034b79 | |||
| a2063f0628 | |||
| acf2f2ffc4 | |||
| d14f484c4b | |||
| 695e515a65 | |||
| 61089feee7 | |||
| ddc9b10cd3 | |||
| f95c92b431 | |||
| eba65a94e6 | |||
| c28a0c6bb8 | |||
| d6bacd9b47 | |||
| 70b1657323 | |||
| 1ef08bd169 | |||
| da68cc6a78 | |||
| 45c75d42ad | |||
| d4e55af2c2 | |||
| 48791a329d | |||
| 9b26ebed75 | |||
| e2160fb6c9 | |||
| 345a1c64f9 | |||
| 7ad1e7756b | |||
| 90caf19e9e | |||
| 8d0b3b7d44 | |||
| 4c253d68d4 | |||
| 73d1b331f1 | |||
| af2fddfd6d | |||
| 3e065ead65 | |||
| 3774704326 | |||
| 4a1100b6a4 | |||
| 63dec77ed6 | |||
| 1d3a66f890 | |||
| c1da92ca22 | |||
| 13475002d7 | |||
| 5bb6f246ed | |||
| 89df7451ef | |||
| 1334d544f7 | |||
| 3fefaa7362 | |||
| 15d62f7b96 | |||
| 83e0aaa511 | |||
| ee06ce1148 | |||
| 16d6124bb4 | |||
| 1197beaa13 | |||
| 98b428a8be | |||
| 17f47d3c0a | |||
| a9cc3b2a89 | |||
| 199102c106 | |||
| c7d76fb7ab | |||
| ba9b86c0dc | |||
| 5de83a606e | |||
| 01a0c8672d | |||
| fa522c0ffc | |||
| 16241d010f | |||
| 9cb8fbf178 | |||
| bd7ef27628 | |||
| 42e520e841 | |||
| d8f9cd237f | |||
| 33065ecf04 | |||
| 718a1da262 | |||
| b89c3ebb42 | |||
| 9d7e44feff | |||
| e48a60a4f0 | |||
| 163e1907a4 | |||
| ac1ccaa246 | |||
| 53b45279ad | |||
| f80daf5de1 | |||
| 298ea1f0d3 | |||
| 1d13d8c4a0 | |||
| 2238c99b61 | |||
| 7d4dfbef2b | |||
| 759827b404 | |||
| fca627d1b0 | |||
| 404da18aed | |||
| 330fca722a | |||
| 8939cd120b | |||
| 63afeb7373 | |||
| 6ba68a6455 | |||
| 1579c74302 | |||
| 373ca15c71 | |||
| a8a3caed1c | |||
| cb35ba4543 | |||
| cdd152d015 | |||
| 83ce7dc62f | |||
| b182b50f24 | |||
| 71a9941b84 | |||
| c777da263e | |||
| 2cb7b56a41 | |||
| 52f9ef14b9 | |||
| 8d6c594240 | |||
| 7ad77ff540 | |||
| acede72e9b | |||
| 771fd732d1 | |||
| 2a79a69f59 | |||
| 8c0321697f | |||
| 0151b3f9b3 | |||
| 82a51f35ea | |||
| 35944cbfc1 | |||
| f0aef9b28b | |||
| ae37c3902c | |||
| d612585582 | |||
| 7ca14d209c | |||
| c37f582c10 | |||
| 6272fb3822 | |||
| 2582fbac59 | |||
| 5abb578e47 | |||
| 015ebf89a5 | |||
| c6724968f1 | |||
| 9fa1772ae4 | |||
| 4551937812 | |||
| 51ee664cae | |||
| fb611a98f9 | |||
| a3d5face38 | |||
| 424cd497d3 | |||
| d46eeffaaf | |||
| 6520f2061e | |||
| 5d93f86b4b | |||
| b3f63ce7ae | |||
| 56de770682 | |||
| 940341bc9d | |||
| 804a0ce601 | |||
| 41054a4c56 | |||
| 7b8e5d4180 | |||
| ca2369f1c1 | |||
| 129cb0b3cd | |||
| 632b2ae1ba | |||
| 18e55061e1 | |||
| e49b65723f | |||
| 8e52894763 | |||
| 07cba6c774 | |||
| 9cb639b505 | |||
| 4cf6eeeee2 | |||
| c0f692792f | |||
| bd77e0945b | |||
| f0eb171b2a | |||
| fb93662b5c | |||
| a26c982e93 | |||
| 7db3e98944 | |||
| 4a87834e04 | |||
| bf6ecaeeb9 | |||
| f70ef86dfa | |||
| cd3132667a | |||
| 1c459a7bea | |||
| 4f0bfeab4c | |||
| c5c9921b59 | |||
| 6b63aba1fc | |||
| 382331fb11 | |||
| caf9af7ae4 | |||
| 45d2adeb9c | |||
| 96708d7592 | |||
| 13090d1219 | |||
| 8ab229cca9 | |||
| 583cd078dc | |||
| aa2ac1bbb8 | |||
| 928b426672 | |||
| 6766b14415 | |||
| 9d0f9e967f | |||
| d7609088e5 | |||
| b2643b6926 | |||
| 07b65ca069 | |||
| 25727f7f99 | |||
| 880ae89307 | |||
| 1496df1989 | |||
| 7d8ae6b4b1 | |||
| 312d4cccaf | |||
| ce5f9f95ea | |||
| d9bf8a76d9 | |||
| f7a35fb9fe | |||
| 3ba691ded5 | |||
| 7a7277d56f | |||
| 76be5dd1d3 | |||
| 53dc63f3bc | |||
| 80da0bc9d5 | |||
| bce7af4e11 | |||
| 9da09b51ed | |||
| 86392f197f | |||
| 1c13046297 | |||
| fbc756b531 | |||
| 6c64b06453 | |||
| 241834029a | |||
| 5b8a9c0b47 | |||
| 037c29d24a | |||
| 893f26ac9a | |||
| d43f8e3100 | |||
| 2b42acf7b8 | |||
| f65b80ed42 | |||
| e84abbdc82 | |||
| 66269eabe9 | |||
| 36c0928483 | |||
| 9237e15adc | |||
| 0d3a2072b2 | |||
| aa2ee5dfc2 | |||
| b515fa39ec | |||
| 76e3f4eb92 | |||
| 4959e5c6c2 | |||
| 7082594bbc | |||
| 36dd35f238 | |||
| 9c9fb6a485 | |||
| 5438a4837b | |||
| 84996e8cb6 | |||
| 87a368a857 | |||
| 21412d93dd | |||
| 0b11ff22b4 | |||
| 8fafa78796 | |||
| c43158f8a2 | |||
| 92ad524947 | |||
| b362a61863 | |||
| 468fec38d7 | |||
| 89830a5ae0 | |||
| 5977c296bd | |||
| 47d5792d97 | |||
| 25d706a913 | |||
| 048236aaaa | |||
| d442c58fd1 | |||
| f890f6bb09 | |||
| 036d466790 | |||
| dee47ba2d8 | |||
| be96c28b77 | |||
| ad1c0f578e | |||
| c8f7b1b72c | |||
| c89702ae84 | |||
| 2d29a82250 | |||
| b36c65e654 | |||
| 09b072b908 | |||
| 0ae9fee350 | |||
| 1579182ed9 | |||
| 074671aa71 | |||
| 36b7c47247 | |||
| 424d5b3025 | |||
| 8a5d352733 | |||
| f383629282 | |||
| a6d717cb04 | |||
| 84a5753301 | |||
| 5d2d9c7e81 | |||
| 82801d1411 | |||
| 340c3963d8 | |||
| ef15cf9847 | |||
| 4d613ccfa7 | |||
| 43ce34d547 | |||
| eda074cd80 | |||
| a2396d82f6 | |||
| a38721db93 | |||
| a06e811717 | |||
| 86e534ff75 | |||
| 640d5b2dec | |||
| 57e9b27085 | |||
| c56eefc739 | |||
| cf28306997 | |||
| 10acf3ddd1 | |||
| fed3ed9f9a | |||
| 260138ba11 | |||
| 67f7e0089c | |||
| d4a22c7851 | |||
| 06cf986490 | |||
| adf9aa04ce | |||
| 69f66fbe52 | |||
| d061005c89 | |||
| f6ee8b9f04 | |||
| 31af22c2ff | |||
| c421e3f243 | |||
| 6e92902407 | |||
| 6256381dc3 | |||
| b247b051ea | |||
| afbd553622 | |||
| 36bc14e884 | |||
| 9c5d0ff2ff | |||
| cfa6c8ddf6 | |||
| 21924bf022 | |||
| eea33f6019 | |||
| 66d48ae808 | |||
| de9b9fd0b1 | |||
| ece7384be4 | |||
| 0c052e4506 | |||
| 1996a0a3d6 | |||
| 679ad9b8c6 | |||
| d4983731e7 | |||
| 4fec3c8f34 | |||
| 836fd2565f | |||
| 54618064a1 | |||
| 519e3e01ae | |||
| aec8f81358 | |||
| c1d6bf4366 | |||
| 9bf2b79d9e | |||
| 4d98408995 | |||
| 7b466388f9 | |||
| b926fb3c66 | |||
| 6c8d5c0d0e | |||
| 5a1d234260 | |||
| fd6d42c297 | |||
| 7310ad6e92 | |||
| 7e47b1348d | |||
| 1e3555a6b7 | |||
| 9a67ce5968 | |||
| 279d7955f8 | |||
| db977c0bf5 | |||
| ba6bc59818 | |||
| 6e8be0578c | |||
| 92f7d16b5e | |||
| 40bb3c2f5e | |||
| 56a6096221 | |||
| ee37b42a91 | |||
| 0806e61df4 | |||
| 279ffeeefa | |||
| 80c5ee2479 | |||
| 16208544e5 | |||
| 6afeb24fdb | |||
| e6357b81eb | |||
| dfc2efe8a6 | |||
| f28b96f431 | |||
| a10293f8f7 | |||
| b1f02f91d7 | |||
| e76fa45d86 | |||
| 06f43892a5 | |||
| a094332b0d | |||
| 7b8779f534 | |||
| 371bf20d19 | |||
| 0f633ddd15 | |||
| 7886ca7f5f | |||
| 9b4c11954d | |||
| a1b724f30a | |||
| 7c3b2fb9cc | |||
| acef68d67e | |||
| 7e393d5f1e | |||
| 955c31b165 | |||
| e307cd48ad | |||
| 25f8b9e451 | |||
| e8ba14a2c1 | |||
| 9670d3341c | |||
| cec9778fd5 | |||
| 7451db4a68 | |||
| e31777ec53 | |||
| 7aa0b3dc7a | |||
| e7b2d5dc01 | |||
| 47d728667d | |||
| e1f8989d54 | |||
| 1d8cb47830 | |||
| faaa7c37a9 | |||
| 0aff9d8df4 | |||
| 30c3f8c1ac | |||
| bcd2469e01 | |||
| 983c6ae73d | |||
| 6d8e1fe776 | |||
| 99b4921309 | |||
| 3c231c3c9e | |||
| 175c0a6236 | |||
| 0031ceb06c | |||
| e3cc5a63df | |||
| 3cb61402c2 | |||
| 5336c51199 | |||
| 52aa658aaa | |||
| d08a51d7e4 | |||
| d97a557ac3 | |||
| 8a68d9cded | |||
| b031f7e902 | |||
| 963ffecb96 | |||
| 8f8aaca818 | |||
| 801f92b7e7 | |||
| 44db45700e | |||
| 25902005f6 | |||
| ffec71e0d8 | |||
| 99a208110b | |||
| e56799c993 | |||
| 957eb300f8 | |||
| 626025d539 | |||
| 9e8a0a020f | |||
| 40f592eade | |||
| 5e899f0be4 | |||
| f2748284b1 | |||
| a15ce00934 | |||
| 9e3e80261b | |||
| c72c685434 | |||
| 0177a8d277 | |||
| b6a9b0a4c9 | |||
| f4f8bd8d42 | |||
| 6e4aeffc0c | |||
| dba256d384 | |||
| 910008e9e7 | |||
| 8cb9545c41 | |||
| 59c16da6fb | |||
| 630df5bbd2 | |||
| f550111400 | |||
| 77377195aa | |||
| 7e2e72bd40 | |||
| aa7a13bd02 | |||
| 5895058a17 | |||
| ffb60d5149 | |||
| 1e2cb279b0 | |||
| e7f766f5ba | |||
| 8de5aa9409 | |||
| bf28a4df49 | |||
| fe1a0ab371 | |||
| 01daccfaf7 | |||
| 94e861e298 | |||
| d36af2ed5c | |||
| 7104b33214 | |||
| 32998e5377 | |||
| af0c9ef092 | |||
| 3bc3b3d10e | |||
| f03f42ca4d | |||
| 79783abeb1 | |||
| 895b0bd602 | |||
| 2ee5ee92f8 | |||
| 3e619423b1 | |||
| b524e18bdf | |||
| 6aa4579db8 | |||
| 17fb86c0f1 | |||
| 62ecfe4873 | |||
| 04e55e6b9a | |||
| f432aa1090 | |||
| 7add104313 | |||
| 36de249066 | |||
| b7a54dcffd | |||
| 6bb28deab2 | |||
| 7f88d15c86 | |||
| 94c5014e23 | |||
| c5a8256500 | |||
| 5f39884bf7 | |||
| d96825a242 | |||
| 443a938091 | |||
| 6bc3197721 | |||
| 269cc91fd5 | |||
| c1ddea479d | |||
| 5f3a95962c | |||
| ee1a8e6a32 | |||
| eeae73296e | |||
| 4ca8357af4 | |||
| 8a5b8c87fb | |||
| 6ab04d7bbc | |||
| a5a1380636 | |||
| eeab1aef64 | |||
| 4e1c342e55 | |||
| d8ed259bce | |||
| 9f6cb5de4c | |||
| ba634118d7 | |||
| 63da091d36 | |||
| ad0dc88a33 | |||
| 147acf4b57 | |||
| 5085f3a15e | |||
| 22a95ad8ea | |||
| df4bd6a60c | |||
| 813e7b05e4 | |||
| ab8b486b4a | |||
| 590f666ec9 | |||
| 9adaee915b | |||
| bce0f06fe9 | |||
| 856ecb84a0 | |||
| 90ddc06c98 | |||
| 405abc4e95 | |||
| 549c59ecf5 | |||
| 0a485eafcb | |||
| e0c11956a6 | |||
| da6a9bf3eb | |||
| dacd11e1cc | |||
| fc854b4c77 | |||
| 4dcc1f0374 | |||
| fc57390242 | |||
| bd15ef0a0c | |||
| 967ecafc33 | |||
| 29576da985 | |||
| 200a2556ef | |||
| ae0ab5025e | |||
| aa74276b25 | |||
| b03112a5dd | |||
| a3f49df62d | |||
| aa2af3f6dd | |||
| 20dcbc593c | |||
| 472ba8c1fd | |||
| d8345a44a4 | |||
| a187cb6c9c | |||
| b89c0b35d1 | |||
| 7ffcc0a5e7 | |||
| bde43fbdfb | |||
| 3728b2208f | |||
| dc52a756ee | |||
| 98dc886841 | |||
| d0cf104e43 | |||
| d7ed2412f6 | |||
| 7d38f0e234 | |||
| 3e8d072d24 | |||
| 84ac771893 | |||
| 3a9e0b5be6 | |||
| 9694ff433f | |||
| 2e82e78b98 | |||
| aaef4bee27 | |||
| 4ca8569488 | |||
| 8377ada3e0 | |||
| 8a034d59ed | |||
| 8e492d8798 | |||
| 7974ef80d7 | |||
| 3664d86430 | |||
| 9adef80d6b | |||
| be57adaee7 | |||
| d117e442a4 | |||
| 8820bc0796 | |||
| 57a64de023 | |||
| 5ed689ceb0 | |||
| 25f1765f36 | |||
| 063bd58802 | |||
| 901c6b34fa | |||
| 5b2d6488a2 | |||
| f6f35415d1 | |||
| 6c6069e963 | |||
| 6219d82560 | |||
| 1dcd7a16ab | |||
| b60caeb9dd | |||
| 4c4768aaf3 | |||
| 2f4ac0a663 | |||
| 23a446f852 | |||
| ec48334a1a | |||
| f4c061d412 | |||
| 31a076d7b3 | |||
| 6bd43d986c | |||
| dd32a2f15a | |||
| c88c20820f | |||
| 86de510731 | |||
| 0b31fbf827 | |||
| 34ad1450eb | |||
| e6ba71390d | |||
| f0c8dbe0ec | |||
| bf046a8ccb | |||
| b05ba7683e | |||
| aedf8dad15 | |||
| 74ebb7c722 | |||
| 1307f66494 | |||
| 448a24cb36 | |||
| 7266f23450 | |||
| c0ad31acfc | |||
| 25d3a0de27 |
@@ -0,0 +1,44 @@
|
||||
# "Gofmt's style is nobody's favourite, but gofmt is everybody's favourite." --Rob Pike
|
||||
#
|
||||
# for clang-format-15.0.6 from https://github.com/upx/upx-stubtools/releases
|
||||
---
|
||||
BasedOnStyle: LLVM
|
||||
ColumnLimit: 100
|
||||
IndentWidth: 4
|
||||
---
|
||||
Language: Cpp
|
||||
AccessModifierOffset: -4
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
AttributeMacros:
|
||||
- __acc_cdecl
|
||||
- __acc_cdecl_atexit
|
||||
- __acc_cdecl_qsort
|
||||
- __acc_cdecl_sighandler
|
||||
- __acc_forceinline
|
||||
- __acc_noinline
|
||||
- __acc_static_noinline
|
||||
- __acc_static_forceinline
|
||||
- forceinline
|
||||
- noinline
|
||||
EmptyLineBeforeAccessModifier: Leave
|
||||
SortIncludes: false
|
||||
SpaceAfterCStyleCast: true
|
||||
Standard: Cpp03
|
||||
StatementMacros:
|
||||
- ACCCHK_ASSERT
|
||||
- ACCCHK_ASSERT_IS_SIGNED_T
|
||||
- ACCCHK_ASSERT_IS_UNSIGNED_T
|
||||
- ACCCHK_ASSERT_SIGN_T
|
||||
- ACC_BLOCK_BEGIN
|
||||
- ACC_COMPILE_TIME_ASSERT
|
||||
- ACC_COMPILE_TIME_ASSERT_HEADER
|
||||
- ACC_CXX_DISABLE_NEW_DELETE
|
||||
- ACC_CXX_TRIGGER_FUNCTION
|
||||
- ACC_CXX_TRIGGER_FUNCTION_IMPL
|
||||
- CLANG_FORMAT_DUMMY_STATEMENT
|
||||
- COMPILE_TIME_ASSERT
|
||||
- COMPILE_TIME_ASSERT_ALIGNED1
|
||||
WhitespaceSensitiveMacros:
|
||||
- ACC_PP_MACRO_EXPAND
|
||||
- ACC_PP_STRINGIZE
|
||||
...
|
||||
@@ -0,0 +1,21 @@
|
||||
# see https://editorconfig.org/
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[{GNUmakefile*,MMakefile*,Makefile*,Makevars*,*.mk}]
|
||||
indent_size = 8
|
||||
indent_style = tab
|
||||
|
||||
[*.S]
|
||||
indent_size = 8
|
||||
|
||||
[*.yml]
|
||||
indent_size = 2
|
||||
@@ -0,0 +1,10 @@
|
||||
# make GitHub language detection more accurate, see https://github.com/github/linguist
|
||||
|
||||
src/*.h linguist-language=C++
|
||||
src/*/*.h linguist-language=C++
|
||||
|
||||
src/stub/**/*.ash linguist-language=Assembly
|
||||
src/stub/**/*.asm linguist-language=Assembly
|
||||
src/stub/**/*.S linguist-language=Assembly
|
||||
|
||||
src/stub/tmp/** linguist-vendored
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
This issue tracker is **ONLY** used for reporting bugs.
|
||||
Please use [stackoverflow](https://stackoverflow.com) for supporting issues.
|
||||
|
||||
<!---
|
||||
|
||||
IF YOU REMOVE THIS TEMPLATE WE WILL CLOSE YOUR ISSUE WITHOUT RESPONSE.
|
||||
Just read it and fill in the details we're asking, it saves so much of our time. Thanks!
|
||||
|
||||
-->
|
||||
|
||||
## What's the problem (or question)?
|
||||
<!--- If describing a bug, tell us what happens instead of the expected behavior -->
|
||||
<!--- If suggesting a change/improvement, explain the difference from current behavior -->
|
||||
|
||||
## What should have happened?
|
||||
<!--- If you're describing a bug, tell us what should happen -->
|
||||
<!--- If you're suggesting a change/improvement, tell us how it should work -->
|
||||
|
||||
## Do you have an idea for a solution?
|
||||
<!--- Not obligatory, but suggest a fix/reason for the bug, -->
|
||||
<!--- or ideas how to implement the addition or change -->
|
||||
|
||||
## How can we reproduce the issue?
|
||||
<!--- Provide unambiguous set of steps to reproduce this bug. Include code to reproduce, if relevant -->
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
4.
|
||||
|
||||
## Please tell us details about your environment.
|
||||
<!--- Include as many relevant details about the environment you experienced the bug in -->
|
||||
* UPX version used (`upx --version`):
|
||||
* Host Operating System and version:
|
||||
* Host CPU architecture:
|
||||
* Target Operating System and version:
|
||||
* Target CPU architecture:
|
||||
@@ -0,0 +1 @@
|
||||
blank_issues_enabled: false
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
This issue tracker is **ONLY** used for requesting sensible features.
|
||||
Please use [stackoverflow](https://stackoverflow.com) for supporting issues.
|
||||
|
||||
<!---
|
||||
|
||||
IF YOU REMOVE THIS TEMPLATE WE WILL CLOSE YOUR ISSUE WITHOUT RESPONSE.
|
||||
Just read it and fill in the details we're asking, it saves so much of our time. Thanks!
|
||||
|
||||
-->
|
||||
|
||||
## What's the problem (or question)?
|
||||
<!--- If describing a bug, tell us what happens instead of the expected behavior -->
|
||||
<!--- If suggesting a change/improvement, explain the difference from current behavior -->
|
||||
|
||||
## What should have happened?
|
||||
<!--- If you're describing a bug, tell us what should happen -->
|
||||
<!--- If you're suggesting a change/improvement, tell us how it should work -->
|
||||
|
||||
## Do you have an idea for a solution?
|
||||
<!--- Not obligatory, but suggest a fix/reason for the bug, -->
|
||||
<!--- or ideas how to implement the addition or change -->
|
||||
|
||||
## How can we reproduce the issue?
|
||||
<!--- Provide unambiguous set of steps to reproduce this bug. Include code to reproduce, if relevant -->
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
4.
|
||||
|
||||
## Please tell us details about your environment.
|
||||
<!--- Include as many relevant details about the environment you experienced the bug in -->
|
||||
* UPX version used (`upx --version`):
|
||||
* Host Operating System and version:
|
||||
* Host CPU architecture:
|
||||
* Target Operating System and version:
|
||||
* Target CPU architecture:
|
||||
@@ -0,0 +1,8 @@
|
||||
version: 2
|
||||
|
||||
updates:
|
||||
- package-ecosystem: 'github-actions'
|
||||
directory: '/'
|
||||
schedule:
|
||||
# Check for updates to GitHub Actions every weekday
|
||||
interval: 'daily'
|
||||
@@ -0,0 +1,14 @@
|
||||
UPX PULL REQUEST NOTES
|
||||
======================
|
||||
|
||||
Handling pull requests is actually quite time consuming, so please
|
||||
|
||||
- if you want to contribute **a real C++ code bug-fix** then open an issue
|
||||
on the main UPX issue tracker first
|
||||
|
||||
- if you want to contribute **a new feature** then by all means open an issue
|
||||
on the main UPX issue tracker first before starting any coding!
|
||||
|
||||
- please refuse the temptation to "improve" the docs, scripts, CI, makefiles,
|
||||
cmake build system, spelling errors, etc - we will NOT merge this; only open
|
||||
an issue if you're sure there is a **real bug**
|
||||
@@ -0,0 +1,15 @@
|
||||
# Security Context
|
||||
|
||||
IMPORTANT NOTE: UPX inherits the security context of any files it handles.
|
||||
|
||||
This means that packing, unpacking, or even testing or listing a file requires
|
||||
the same security considerations as actually executing the file.
|
||||
|
||||
Use UPX on trusted files only!
|
||||
|
||||
## Supported Versions
|
||||
|
||||
| Version | Supported |
|
||||
| --------- | ------------------ |
|
||||
| git HEAD | :white_check_mark: |
|
||||
| any other | :x: |
|
||||
@@ -0,0 +1,209 @@
|
||||
########## begin .sha256sums.recreate
|
||||
expected_sha256sums__t010_decompressed="\
|
||||
24158f78c34c4ef94bb7773a6dda7231d289be76c2f5f60e8b9ddb3f800c100e *amd64-linux.elf/upx-3.91
|
||||
24808d572483f4cd713d66894b3da406755038737007a78b076528e6407e3132 *amd64-linux.elf/upx-3.95
|
||||
d88eaad0528bcecec9f51cbe015a117c8cf350a3f6d8308f2b0517d4fd19d189 *amd64-win64.pe/upx-3.95.exe
|
||||
f7279729eb975e4238f8b8ee56fefa41ccbeb35ef0ffe4c34f8047baab78fff5 *arm-linux.elf/upx-3.95
|
||||
e09df2a69f88c692138447f274ba7f99cdd11f8696c71ac8d3761606c95ab5c5 *arm-wince.pe/upx-3.91.exe
|
||||
ce81113f8a4ff1cd806811cb80ab8bea5c9c6fbced47451c7f07e50700f9817b *arm64-linux.elf/upx-3.95
|
||||
b1c1c38d50007616aaf8e942839648c80a6111023e0b411e5fa7a06c543aeb4a *armeb-linux.elf/upx-3.91
|
||||
84b90eb0d617571fe4885639925b35ca6a61060cb2616bb5bf729b4d701653e4 *armeb-linux.elf/upx-3.95
|
||||
bcac77a287289301a45fde9a75e4e6c9ad7f8d57856bae6eafaae12ae4445a34 *i386-dos32.djgpp2.coff/upx-3.91.exe
|
||||
7d331e508449497f64cd47abdd3f00f70307f508ad3fd692d333feb97beccead *i386-dos32.djgpp2.coff/upx-3.95.exe
|
||||
730a513b72a094697f827e4ac1a4f8ef58a614fc7a7ad448fa58d60cd89af7ed *i386-linux.elf/upx-3.91
|
||||
a1f3e5ffa7b2cfebe1e475ac1f4c7683b1b8b4e292aa0d04386cc0314dd162c9 *i386-linux.elf/upx-3.95
|
||||
e90fb09a808334c2674996760d42c82f8352e3f671f6b66c11481e772785c4d2 *i386-win32.pe/upx-3.91.exe
|
||||
07bd50c1d80f6ff651228e6fc0ba3a583a472915772244f232696b34156a9d27 *i386-win32.pe/upx-3.95.exe
|
||||
8e5333ea040f5594d3e67d5b09e005d52b3a52ef55099a7c11d7e39ead38e66d *m68k-atari.tos/upx-3.91.ttp
|
||||
8902f38ec3d95d8e077e3ab5fdbb5bad408859913a35deb87041f4f053cd6605 *mips-linux.elf/upx-3.95
|
||||
c3f44b4d00a87384c03a6f9e7aec809c1addfe3e271244d38a474f296603088c *mipsel-linux.elf/upx-3.91
|
||||
dd1496bc4e9c32a5d5dd47e3eaabf7b134ca001d48807eebfd3d5e28c8a2ab58 *mipsel-linux.elf/upx-3.95
|
||||
b8c35fa2956da17ca505956e9f5017bb5f3a746322647e24ccb8ff28059cafa4 *powerpc-linux.elf/upx-3.91
|
||||
2bc00a51daa0bada19a8fa1bd2c227a8596844fa1b0aa3611087f195072700e2 *powerpc-linux.elf/upx-3.95
|
||||
a0950546dc17fca9437219431d8ddb0249ce5b08e899e0c799a87ac982adee70 *powerpc64le-linux.elf/upx-3.95
|
||||
"
|
||||
expected_sha256sums__t020_canonicalized="\
|
||||
24158f78c34c4ef94bb7773a6dda7231d289be76c2f5f60e8b9ddb3f800c100e *amd64-linux.elf/upx-3.91
|
||||
24808d572483f4cd713d66894b3da406755038737007a78b076528e6407e3132 *amd64-linux.elf/upx-3.95
|
||||
d88eaad0528bcecec9f51cbe015a117c8cf350a3f6d8308f2b0517d4fd19d189 *amd64-win64.pe/upx-3.95.exe
|
||||
f7279729eb975e4238f8b8ee56fefa41ccbeb35ef0ffe4c34f8047baab78fff5 *arm-linux.elf/upx-3.95
|
||||
e09df2a69f88c692138447f274ba7f99cdd11f8696c71ac8d3761606c95ab5c5 *arm-wince.pe/upx-3.91.exe
|
||||
ce81113f8a4ff1cd806811cb80ab8bea5c9c6fbced47451c7f07e50700f9817b *arm64-linux.elf/upx-3.95
|
||||
b1c1c38d50007616aaf8e942839648c80a6111023e0b411e5fa7a06c543aeb4a *armeb-linux.elf/upx-3.91
|
||||
84b90eb0d617571fe4885639925b35ca6a61060cb2616bb5bf729b4d701653e4 *armeb-linux.elf/upx-3.95
|
||||
bcac77a287289301a45fde9a75e4e6c9ad7f8d57856bae6eafaae12ae4445a34 *i386-dos32.djgpp2.coff/upx-3.91.exe
|
||||
7d331e508449497f64cd47abdd3f00f70307f508ad3fd692d333feb97beccead *i386-dos32.djgpp2.coff/upx-3.95.exe
|
||||
730a513b72a094697f827e4ac1a4f8ef58a614fc7a7ad448fa58d60cd89af7ed *i386-linux.elf/upx-3.91
|
||||
a1f3e5ffa7b2cfebe1e475ac1f4c7683b1b8b4e292aa0d04386cc0314dd162c9 *i386-linux.elf/upx-3.95
|
||||
e90fb09a808334c2674996760d42c82f8352e3f671f6b66c11481e772785c4d2 *i386-win32.pe/upx-3.91.exe
|
||||
07bd50c1d80f6ff651228e6fc0ba3a583a472915772244f232696b34156a9d27 *i386-win32.pe/upx-3.95.exe
|
||||
8e5333ea040f5594d3e67d5b09e005d52b3a52ef55099a7c11d7e39ead38e66d *m68k-atari.tos/upx-3.91.ttp
|
||||
8902f38ec3d95d8e077e3ab5fdbb5bad408859913a35deb87041f4f053cd6605 *mips-linux.elf/upx-3.95
|
||||
c3f44b4d00a87384c03a6f9e7aec809c1addfe3e271244d38a474f296603088c *mipsel-linux.elf/upx-3.91
|
||||
dd1496bc4e9c32a5d5dd47e3eaabf7b134ca001d48807eebfd3d5e28c8a2ab58 *mipsel-linux.elf/upx-3.95
|
||||
b8c35fa2956da17ca505956e9f5017bb5f3a746322647e24ccb8ff28059cafa4 *powerpc-linux.elf/upx-3.91
|
||||
2bc00a51daa0bada19a8fa1bd2c227a8596844fa1b0aa3611087f195072700e2 *powerpc-linux.elf/upx-3.95
|
||||
a0950546dc17fca9437219431d8ddb0249ce5b08e899e0c799a87ac982adee70 *powerpc64le-linux.elf/upx-3.95
|
||||
"
|
||||
expected_sha256sums__t110_compress_ucl_nrv2b_3_no_filter="\
|
||||
693102863358cc906bce946afec10dd0e15d0effc6ceb462d9beaaba25967304 *amd64-linux.elf/upx-3.91
|
||||
4aa9e1868d7797b50768cf1ae0ab0e93cc2eff81f3abaf36f2fdb5faf673f7b7 *amd64-linux.elf/upx-3.95
|
||||
996dc60b7b6aa8c4c55b4fbec9b1ad3e2f82f9986fd1cdcd2cb41ab01877d5a9 *amd64-win64.pe/upx-3.95.exe
|
||||
bb6cd600a28de3abc86c618125d72231d3d4b40de0260d2da7393970859723dd *arm-linux.elf/upx-3.95
|
||||
bc945bc3f64a318a00ecbfde2e4a4bac2d298f753e5a8dbdc6a972bcabfce6eb *arm-wince.pe/upx-3.91.exe
|
||||
19bdd27706f3476dfd46e5cdde782908af5bf9d068bf337ad8a26024d51ede8f *arm64-linux.elf/upx-3.95
|
||||
3b6e5e9eeb660859e35d9d3e005fb51a8163bfe548d8be6525660a30d1ea5c37 *armeb-linux.elf/upx-3.91
|
||||
2f2d916ee977e06b07429e563aeab0d052b7ba359dd61a7d767e2a7ef7fa049d *armeb-linux.elf/upx-3.95
|
||||
1e8cded938d4ee16bcc66fb5462650733a8862a1c9fab264a77a22e7958b36a7 *i386-dos32.djgpp2.coff/upx-3.91.exe
|
||||
6f439d62cdb735570c6c5e941924b6d2819024cad6c3453db020edc1e9e0d66b *i386-dos32.djgpp2.coff/upx-3.95.exe
|
||||
f6a8a76b9af29272722be6785242a9822ce6b2ca3483cd953c2c34e4d85e1cf4 *i386-linux.elf/upx-3.91
|
||||
7eead732dddffdb1db5e5002babe112f8589eeb8251cb23e0b6f29dacfad3817 *i386-linux.elf/upx-3.95
|
||||
2c41d77ae9ac810cde23a222046d05b57a272c90aa75b127e0697a586be1ce1f *i386-win32.pe/upx-3.91.exe
|
||||
0218c00a3686363148a2bbe7d89634d54a2d7840beeab7f5fef2f269e56d517e *i386-win32.pe/upx-3.95.exe
|
||||
44034fc9a3609538d8edfbe3996aa3946b1745e537d1ea2ca14181c177b98034 *m68k-atari.tos/upx-3.91.ttp
|
||||
55c6151325fdf1638584f0fa5ee228547445e239bb0c8f4c6f31c30945e114b1 *mips-linux.elf/upx-3.95
|
||||
b6905f55277b3abc8ad10eb1ca95135ce9f2a5d87c992f7de78ca8e69d8e819e *mipsel-linux.elf/upx-3.91
|
||||
3a5eb4b01cb334e4a30a0ebb1c7d9f85f2035e6e5989acc296beb3ff34c98152 *mipsel-linux.elf/upx-3.95
|
||||
df4157e8e613f62fb26b1965b1c22dc44bf18f4aec4611283afadb9889d267d4 *powerpc-linux.elf/upx-3.91
|
||||
054a126aa7e17c6c5b8a00f608c4bf98f252ec4ab9ca2c03aebf9c92e30bda4f *powerpc-linux.elf/upx-3.95
|
||||
4667d37cb2474a30b184cd4d7ca8ba071650c396ebe9f1f9a39172c924676090 *powerpc64le-linux.elf/upx-3.95
|
||||
"
|
||||
expected_sha256sums__t120_compress_ucl_nrv2d_3_no_filter="\
|
||||
f3cfc0be5885525965fbd3e56f5a4083a727414978bb4c018b4b0355c5b06921 *amd64-linux.elf/upx-3.91
|
||||
06f933cf1c5e42f2f00ffb6a5312fa687846b6a566d372459208f8cad34e34bb *amd64-linux.elf/upx-3.95
|
||||
db33236e886947a74c766e632ded0249166e2e5f74a3d03cda37cc07901cd1b1 *amd64-win64.pe/upx-3.95.exe
|
||||
3564858c026c2b0637e3c8e41a972fabc609ccc69c7ddd0ae457dd4ba7a62008 *arm-linux.elf/upx-3.95
|
||||
dceda960aa7b15b13a06bf88d1512d52e7e460d85a81207b6b5407bdbb51ffe8 *arm-wince.pe/upx-3.91.exe
|
||||
52b93b549591081ef72d19fe09d4588d7f2bc736f2ad50a32be03fb7fcd70e95 *arm64-linux.elf/upx-3.95
|
||||
1877be1f5f5333f1ee7c77bfb020f35f5c125e7f6b661a92a6918b468c02484f *armeb-linux.elf/upx-3.91
|
||||
a4d1f01a3dc748e92dd33e1377885ef2955c2c35fd379474c6622ce67267fac2 *armeb-linux.elf/upx-3.95
|
||||
d5d3cf6ecf1a89f5871bcfef9c59794f249b9f7ca12afdf15b79d343a18ddefc *i386-dos32.djgpp2.coff/upx-3.91.exe
|
||||
eca16dec497e1a9f334fd4d806f035cafcd3438749d25b494e95f4935760ae4f *i386-dos32.djgpp2.coff/upx-3.95.exe
|
||||
1ab8d00e13d149f6e74187eadaacd1d8cfa4777ce7489cef88fba4cbde9bcdee *i386-linux.elf/upx-3.91
|
||||
dd3169256039f7df2db15a86114818b275c03bd96c3ee828d724131b98fcc6f2 *i386-linux.elf/upx-3.95
|
||||
17a97d24ebbdaa3bd8f7ec9633e38bca1754c8af2d79250aaa5472499a98e0ec *i386-win32.pe/upx-3.91.exe
|
||||
1bb873ed8a8cbb11238f98c3f616ec6a34f4765a6021e10d9686158f382458f0 *i386-win32.pe/upx-3.95.exe
|
||||
13b0b57643342d0e08fe084cbf799f518b3d44ac9f39edda7db3e6b6c36386cc *m68k-atari.tos/upx-3.91.ttp
|
||||
91145a85e926495a536661d4e842a7b5b259707ef6accf5f08d13adcec173f13 *mips-linux.elf/upx-3.95
|
||||
8090533000872748b70c761d5581d78fde421d66884ab238527ca41d1446c2ae *mipsel-linux.elf/upx-3.91
|
||||
f82e7b166647f157c981af92eaeec63bf080609591a5d13f76f84cd49c8e7495 *mipsel-linux.elf/upx-3.95
|
||||
ae312cc5d34fd889ed9582a928ab03c589c0caddb111aceade7e072f928c6361 *powerpc-linux.elf/upx-3.91
|
||||
fd28cb894be895afb8aec675739b276810e7a35c5212016c3f7acde853d8c763 *powerpc-linux.elf/upx-3.95
|
||||
e299bb500c34d2f90b2b35a7186a0b24fb5ac80e56d4a2d80f9c8bd32cf2be62 *powerpc64le-linux.elf/upx-3.95
|
||||
"
|
||||
expected_sha256sums__t130_compress_ucl_nrv2e_3_no_filter="\
|
||||
eea59d6755beed52bff26941d31362f28097d029d4f61a2f9065dcc63cd628fb *amd64-linux.elf/upx-3.91
|
||||
b89f4ca39165071a7a5eb107ed9b7c6c77b7c7ad90acdb2b073314571aacc23a *amd64-linux.elf/upx-3.95
|
||||
6af6bc4f2d4bdb1e7694f44ce695c54d181011b734f159018d5e2c515d14a47c *amd64-win64.pe/upx-3.95.exe
|
||||
9ae22ad9af331ec8c08ab22b0a8e0e0ff849512a6d11257c55fe7c423c0b7937 *arm-linux.elf/upx-3.95
|
||||
8605ddb612a1a3e096e272cb876e7777585804fa000f338f2164437a6da3de9a *arm-wince.pe/upx-3.91.exe
|
||||
2ab36b41db84e6e3002420ec397d79abed451869a7a8b703ab3b81f79c487753 *arm64-linux.elf/upx-3.95
|
||||
38879c80525760492a95de9bfcbce49997c5bff30bb43a6bb173b1978d21f248 *armeb-linux.elf/upx-3.91
|
||||
72e3bf259bf1304235a7ebe600f5b37be21297b8552f2fbdf47e28e3aa19e807 *armeb-linux.elf/upx-3.95
|
||||
3af56cb84be62f4078ae39be3370ef68061b094c62b3cbcd5d38e99e0e91df7f *i386-dos32.djgpp2.coff/upx-3.91.exe
|
||||
224b882b4dcebc1112ced3df1b468ea8dc58083dac4893fa0061dc50ce6abf7c *i386-dos32.djgpp2.coff/upx-3.95.exe
|
||||
59e3a1d456036bed175056978d12484a64405f356b1a1fa480866e7e31c9543b *i386-linux.elf/upx-3.91
|
||||
9662deb5f74b23c5b63d09457442895091f4b6cfd619f7bd6ffc27ec75f08682 *i386-linux.elf/upx-3.95
|
||||
3c585a745cd105073bb7324f2183731be84cfc4669f2bab1ef20c9bff909d2fc *i386-win32.pe/upx-3.91.exe
|
||||
fc796dad77cb6cb99bcb5700c3ff0a7b185c1fe8b129a293dd0e45d0903b13e6 *i386-win32.pe/upx-3.95.exe
|
||||
da41cb691775b8b0ef969954ea272262ed77e83b57257b2ba0ba19427a2ab991 *m68k-atari.tos/upx-3.91.ttp
|
||||
ea6ff916a226e39a5e67b2118fc3ceb0dbc69d8d473051a5df19af14e03ae25e *mips-linux.elf/upx-3.95
|
||||
0cbc8eaecb2aa7dcc2e9d7b11ba0c0e26193f1328a35107cf1069a8c5f9e63be *mipsel-linux.elf/upx-3.91
|
||||
7b112c59fccf3e5f3d4ec253fdb25761e47705a1c5d3a0103249b1747bbbe7d9 *mipsel-linux.elf/upx-3.95
|
||||
de8354fbeaf0623f3d08c3945dcdb5a8f0c078fe3e8082a13767979e841e6677 *powerpc-linux.elf/upx-3.91
|
||||
403c26bc1dda0cbf23032bc5ec5ac42ed8537a640a077c4332446227c8a3eb7b *powerpc-linux.elf/upx-3.95
|
||||
093a7fdbb555c8aea8728b4d6240ed3b723ee9007c5f6ea40a8daf2d1eb63f54 *powerpc64le-linux.elf/upx-3.95
|
||||
"
|
||||
expected_sha256sums__t140_compress_lzma_2_no_filter="\
|
||||
6dd472386ff2a9683d75fe4cc8d0d40be223681f4d7305a51a7aacf25501e60f *amd64-linux.elf/upx-3.91
|
||||
4bbb96b109ae2b8b43b957bc66c3cdc2cfcf3a692377153ef912d09a495c876c *amd64-linux.elf/upx-3.95
|
||||
510fc860ac393abcfdbb547e999c12a6c6e928ead026607a6879fa7ca1e2d568 *amd64-win64.pe/upx-3.95.exe
|
||||
a54c0e5b61257154c56f076460f64efbb4216c913c846073d0a695ac3c0ddffd *arm-linux.elf/upx-3.95
|
||||
9182294f2e31db89b138294cbbc6f6d03ea39a00565adf0e052ed3d21491e1b5 *arm-wince.pe/upx-3.91.exe
|
||||
fde8face710b6a479a96d7d2d40a29ac8894d5483403e33acbf4a5d6f9cdb29d *arm64-linux.elf/upx-3.95
|
||||
0a92af3f6034487034ea062bc44c93bba74219fa5fdcbb34d1643a95f7daa9ed *armeb-linux.elf/upx-3.91
|
||||
2c11ec89ad145e9f82c3cbbd63ed1e1eca2b0d3c3081fce3e0500ed33c05a623 *armeb-linux.elf/upx-3.95
|
||||
13cbcb06079492a21b7440b981250f84ff2be48a69daa168d95cee798f8fbf77 *i386-dos32.djgpp2.coff/upx-3.91.exe
|
||||
adfdcd033340a7b14945c9a60da036e25d44c8b1ee0811ac0a4ef1cbca423cc5 *i386-dos32.djgpp2.coff/upx-3.95.exe
|
||||
e5fff5b965da26349311c0513d09086600c3b466f1d53e42d6e35d6b4656168e *i386-linux.elf/upx-3.91
|
||||
cf8df3858bbb1c92a06e57ce1b971e11bbf280954f2fc1dc7e5b5a4641d72819 *i386-linux.elf/upx-3.95
|
||||
ddc4952ef008b7f31e69bf53310d6f03b36a959ebb1cd3c3985d560efcbd4296 *i386-win32.pe/upx-3.91.exe
|
||||
99b0b637b562798a440ba605d44e34cf7d4ff995b04dc2e54ebee288ed5180b4 *i386-win32.pe/upx-3.95.exe
|
||||
89a5de403a012256afefff0f88e1cff4696dee611946e326ad15416dbdba7d13 *m68k-atari.tos/upx-3.91.ttp
|
||||
eac695bc19163050c5bee9271393156a195bfef9c3c76f5aaf3aaef00f5602eb *mips-linux.elf/upx-3.95
|
||||
b1331b88421cdf8ef73f8ef1a2c86045fc56a495c08d06d83018c88f5f3934de *mipsel-linux.elf/upx-3.91
|
||||
9644118e26647d489e811ebe3bfd320e2976dbe26621e994fe979b0f9d175818 *mipsel-linux.elf/upx-3.95
|
||||
64a4a31815e4bf43e2ea866faa494c69a4209ed53055f16562d0d2d6ba7fd927 *powerpc-linux.elf/upx-3.91
|
||||
dec559bf9cbd4d1745e8f3bf2cedf016a72f443d037f75eab0d2baab191f0ae1 *powerpc-linux.elf/upx-3.95
|
||||
f10b8afa319b1056a82f24dd52d13003c5cf005fc3cc3481dad1e58ef33e973f *powerpc64le-linux.elf/upx-3.95
|
||||
"
|
||||
expected_sha256sums__t150_compress_ucl_2_all_filters="\
|
||||
2e89a5b8192957b066d5a5ee39e47663518f49c1e7811f6806e21d938201d5b6 *amd64-linux.elf/upx-3.91
|
||||
d1cfdda4b93d697211c052f3d85cd745e533261f05cc06c2869a8561c07b4f57 *amd64-linux.elf/upx-3.95
|
||||
c7381363e31af6789111f58ca590b0d751956c322684efa1914f1d918ecc23ce *amd64-win64.pe/upx-3.95.exe
|
||||
4dc8ba75edd4b1c3d890c9deeb033d9abf08fb65054eddb4f34138d34503c21d *arm-linux.elf/upx-3.95
|
||||
36f744d6dca6ecb8c60ee456859ac6a1ac241d12ababa20a5e2d0d79551d53aa *arm-wince.pe/upx-3.91.exe
|
||||
72d3de2abdc3985c790d833a9535054683e2b3feaa6b96778e55ea8f448846a3 *arm64-linux.elf/upx-3.95
|
||||
233d4f130995bb7155064ce6f651b9f6ac61268c8698ccc90a8ea3b2e297cb39 *armeb-linux.elf/upx-3.91
|
||||
a107428a7675181974a8efc359d39da74510098d8307347865f7bcdd707e28ad *armeb-linux.elf/upx-3.95
|
||||
bd57c1e3844310c2a864384f2b83a5781933a5beb05a5eb748a6094e37621166 *i386-dos32.djgpp2.coff/upx-3.91.exe
|
||||
1a13debece417ada4e18d5ec02efa7ef1c354ddfa4674b5717e0aa6bc90c16e3 *i386-dos32.djgpp2.coff/upx-3.95.exe
|
||||
f7b56af17d3d8402310387d1e82f90fa670dfa058feb3fe413ac81c01a1efbb1 *i386-linux.elf/upx-3.91
|
||||
fe9162fbfe8f4eb1c9f286df68107c08f25592d2edaaf5707540c81f709e29ac *i386-linux.elf/upx-3.95
|
||||
aaa267d824bd0520c016edcc1a6642d4898030760879e1da883b8211cf071350 *i386-win32.pe/upx-3.91.exe
|
||||
d178699c0ed805829e457987ea5da21f4e37cf1eb74529235d9b1275bf3122f6 *i386-win32.pe/upx-3.95.exe
|
||||
8376ba3954c4fd9cd5e5e8e38923759db005a4048c3d86dc76476e9f3d92a07d *m68k-atari.tos/upx-3.91.ttp
|
||||
65a0227127b7952a42216c79a8431d1bbe7f04c9efdc81f72095d095a969cb80 *mips-linux.elf/upx-3.95
|
||||
c2bd45b55980bfbc5e568a640643772e3e82bc02cd2c7559cb1c57fc0809d01e *mipsel-linux.elf/upx-3.91
|
||||
74e25daba42baeaaffadab00bacca56b1de5f151a00160592077288a678f41f2 *mipsel-linux.elf/upx-3.95
|
||||
904310944bec344897fc6b7a61dfe8ee639d136c555a950c736059cbc6cac8be *powerpc-linux.elf/upx-3.91
|
||||
5304a95cdcdbdcb76cfac2b93e254f601fb73f68be0a44ed282096aec8d55ae8 *powerpc-linux.elf/upx-3.95
|
||||
7ebd0be91bc9f60e22304103b3543b16a0fd128aa22f11474e31aecc97703e43 *powerpc64le-linux.elf/upx-3.95
|
||||
"
|
||||
expected_sha256sums__t160_compress_all_methods_1_no_filter="\
|
||||
4d8069614af5721c7878daf10ee1d30a6bffc5446532963e2ff0e6cb6f1feecd *amd64-linux.elf/upx-3.91
|
||||
f1971902f7d8f840fdc70ad9edbf5587db556ba046947f5ee7b4130e9ba7de5a *amd64-linux.elf/upx-3.95
|
||||
0198a6cfd468f7ec7cd32294333400a4c97bf1cac32602594681db8f08c87700 *amd64-win64.pe/upx-3.95.exe
|
||||
d46340dcd209cce0f1d65d6a50754ea3246cdbba730199765b2c2ac40957bd55 *arm-linux.elf/upx-3.95
|
||||
aa03361a7dae633d5b6c8b4164726c99bfc28fcf4f1ac8ebea6fc44e90c03244 *arm-wince.pe/upx-3.91.exe
|
||||
aa0a3dda3e2f073eb36d6614c02f4af79590876a23437623ea6c231be8e070fa *arm64-linux.elf/upx-3.95
|
||||
578547a4d527655c7fd661148dfcf0f7dc9585dfb08063c13b116364a881bf15 *armeb-linux.elf/upx-3.91
|
||||
0034809b31b0105631b0e4c0a4378cfd26a80dfca2016228e8084f410025f091 *armeb-linux.elf/upx-3.95
|
||||
55b9b578a97a7b8637a9041a222269f2563a4e1f75c329c533f83432c8f9652c *i386-dos32.djgpp2.coff/upx-3.91.exe
|
||||
98a9f601d095f910c68bbf35ff50f19e3e851ef5dae78fc0e9ef4462dd8a314d *i386-dos32.djgpp2.coff/upx-3.95.exe
|
||||
45f714365212b31419986016b5b730ca77523036469e28242543bfde4dc44678 *i386-linux.elf/upx-3.91
|
||||
e45f6ae7ad7b9e719e5080bfbd04e7c961242473bb8f1574cb625bc8a1abd201 *i386-linux.elf/upx-3.95
|
||||
0b5d940059fc6f2a3d5664eadd0781399210c306be99411beeb8f6f02ea85762 *i386-win32.pe/upx-3.91.exe
|
||||
0f5b50dfe0db34ae07f113871a39c64624f964ed16dc8d49922e6a891c17a3bd *i386-win32.pe/upx-3.95.exe
|
||||
56fd999694feb66cdc2272daf86bb91b3c66b857867f3e0c071f3e70624760f4 *m68k-atari.tos/upx-3.91.ttp
|
||||
2d8d2e02bedad8ba1e7d69a89888b173b9be48ee154e2461c205ba4eae6ececa *mips-linux.elf/upx-3.95
|
||||
c478c21ecabe91910cf861ebc6b6d38deeb31545e5ae44eaf826dafb477bbfba *mipsel-linux.elf/upx-3.91
|
||||
4d66e1b32ca6b1d399616de5643ee5d1c54a7bf1eca761055570450f56efe4f9 *mipsel-linux.elf/upx-3.95
|
||||
72c85b48afb30cc191483af41f797a397225cfaaa44e2eaf7a9d59d9033335e1 *powerpc-linux.elf/upx-3.91
|
||||
c0ed0c72fd6a6e0bfb4444b8c358018246f80cbc732388a22bd2492fd9fdc59c *powerpc-linux.elf/upx-3.95
|
||||
070f4c2ca60717abedda0ab4030d546cca8a75b9872038a414e2946b8d8f93e7 *powerpc64le-linux.elf/upx-3.95
|
||||
"
|
||||
expected_sha256sums__t170_compress_all_methods_no_lzma_5_no_filter="\
|
||||
223bcdc5f11daa4d0258090e967d4e0b5986d764d6b21fcfadba7212676396f2 *amd64-linux.elf/upx-3.91
|
||||
a3e5f1a20bd9db4ae920c5c7e7f1707a63fa3f557f9db50b5e1004b706e3a52c *amd64-linux.elf/upx-3.95
|
||||
355011427a4d433ccef5060e4cbebc59b0ecc38a430566cdb684330388ea0812 *amd64-win64.pe/upx-3.95.exe
|
||||
1e0a8363b539953181dc95283a1e3100bacce961f49e875c8f430b18d0e6672d *arm-linux.elf/upx-3.95
|
||||
e281362e2172468d20ea2c7171c847f47e01a63d912cafacf977236655708521 *arm-wince.pe/upx-3.91.exe
|
||||
7f3497c67e816b3f2af6642f09ba809166f8a0a65f52936cfb2e3d9756d7bd44 *arm64-linux.elf/upx-3.95
|
||||
7d9d52959a64c5dd19ea343c8c2bdd4d70fd0644d13c62924760407515fd74ba *armeb-linux.elf/upx-3.91
|
||||
e05ad251ec24e2f788de71c4c8cf7c8880a8eb7d8a516ca8d6ab94c715c2f77d *armeb-linux.elf/upx-3.95
|
||||
00a030d8967c5145b955eba17d84edd44b21c93b570f80a44e894a10a3ebf99f *i386-dos32.djgpp2.coff/upx-3.91.exe
|
||||
b4b0e3c774dbf3940af777d28e1ba7c62bfedaa710e3376e81259218779eae56 *i386-dos32.djgpp2.coff/upx-3.95.exe
|
||||
f903265140b193e672c4dd2bc28e68b9f822d73517f0b339fc715ad781a49fab *i386-linux.elf/upx-3.91
|
||||
6253062e41c4619bb3aeb807665a2925b1f01095d000c614c443b81d44112a1d *i386-linux.elf/upx-3.95
|
||||
7664ed4ce00b962a21ca5654993c4c4cb2ec1afcf9dc921cd90862f8412572cc *i386-win32.pe/upx-3.91.exe
|
||||
6ef354d0b2dffc71c32fc33f3f89b0b8ae7035e43e8a684a12d6ce2c53caf706 *i386-win32.pe/upx-3.95.exe
|
||||
5890050fe690bb93bf70693f1bef0e6ea708029836c7d8aa57de02b6aefe4239 *m68k-atari.tos/upx-3.91.ttp
|
||||
2bce2082ae39dedcc21a1a6c83e954073b368e9172ee0c7f2a3f13b3447a7898 *mips-linux.elf/upx-3.95
|
||||
d5b88d291a8a2141d9d9f07a6a21e11522e510c6520ba0c36ebf94d089962607 *mipsel-linux.elf/upx-3.91
|
||||
ff42d564999e02346c86d4156266f423edd55b3887aadf76d81a8c355e3b175d *mipsel-linux.elf/upx-3.95
|
||||
f33205ad8252524d8c48d18cdb03bba507e29c9cc931f94327a5a46480f70843 *powerpc-linux.elf/upx-3.91
|
||||
011683a891e30ea346efe9ba5c1488fb50f143e4090bd2be07537c696d6167db *powerpc-linux.elf/upx-3.95
|
||||
9d919460b0ceec4b880cdf14850fea8096d6796c2457467b3cc9b2ce954cc6de *powerpc64le-linux.elf/upx-3.95
|
||||
"
|
||||
########## end .sha256sums.recreate
|
||||
@@ -0,0 +1,290 @@
|
||||
#! /bin/bash
|
||||
## vim:set ts=4 sw=4 et:
|
||||
set -e; set -o pipefail
|
||||
argv0=$0; argv0abs=$(readlink -en -- "$0"); argv0dir=$(dirname "$argv0abs")
|
||||
|
||||
# very first version of the upx-testsuite; requires:
|
||||
# $upx_exe
|
||||
# $upx_testsuite_SRCDIR
|
||||
# $upx_testsuite_BUILDDIR (optional)
|
||||
# $BM_T (optional)
|
||||
|
||||
# convenience
|
||||
[[ -z $upx_testsuite_BUILDDIR ]] && upx_testsuite_BUILDDIR=./tmp-upx-testsuite
|
||||
[[ -f $upx_exe ]] && upx_exe=$(readlink -en -- "$upx_exe")
|
||||
|
||||
# make dirs absolute
|
||||
upx_testsuite_SRCDIR=$(readlink -en -- "$upx_testsuite_SRCDIR")
|
||||
if [[ ! -d "$upx_testsuite_SRCDIR/files/packed" ]]; then
|
||||
echo 'invalid or missing $upx_testsuite_SRCDIR:'
|
||||
echo ' please git clone https://github.com/upx/upx-testsuite'
|
||||
echo ' and set (export) the envvar upx_testsuite_SRCDIR to the local file path'
|
||||
exit 1
|
||||
fi
|
||||
mkdir -p "$upx_testsuite_BUILDDIR"
|
||||
upx_testsuite_BUILDDIR=$(readlink -en -- "$upx_testsuite_BUILDDIR")
|
||||
|
||||
cd / && cd "$upx_testsuite_BUILDDIR" || exit 1
|
||||
|
||||
# /***********************************************************************
|
||||
# // support functions
|
||||
# ************************************************************************/
|
||||
|
||||
testsuite_header() {
|
||||
local x='==========='; x="$x$x$x$x$x$x$x"
|
||||
echo -e "\n${x}\n${1}\n${x}\n"
|
||||
}
|
||||
|
||||
testsuite_split_f() {
|
||||
fd=$(dirname "$1")
|
||||
fb=$(basename "$1")
|
||||
fsubdir=$(basename "$fd")
|
||||
# sanity checks
|
||||
if [[ ! -f $1 || -z $fsubdir || -z $fb ]]; then
|
||||
fd= fb= fsubdir=
|
||||
fi
|
||||
}
|
||||
|
||||
testsuite_check_sha() {
|
||||
(cd "$1" && sha256sum -b */* | LC_ALL=C sort -k2) > $1/.sha256sums.current
|
||||
echo
|
||||
cat $1/.sha256sums.current
|
||||
if ! cmp -s $1/.sha256sums.expected $1/.sha256sums.current; then
|
||||
echo "UPX-ERROR: $1 FAILED: checksum mismatch"
|
||||
diff -u $1/.sha256sums.expected $1/.sha256sums.current || true
|
||||
exit_code=99
|
||||
let num_errors+=1 || true
|
||||
all_errors="${all_errors} $1"
|
||||
#exit 99
|
||||
fi
|
||||
echo
|
||||
}
|
||||
|
||||
testsuite_check_sha_decompressed() {
|
||||
(cd "$1" && sha256sum -b */* | LC_ALL=C sort -k2) > $1/.sha256sums.current
|
||||
if ! cmp -s $1/.sha256sums.expected $1/.sha256sums.current; then
|
||||
cat $1/.sha256sums.current
|
||||
echo "UPX-ERROR: FATAL: $1 FAILED: decompressed checksum mismatch"
|
||||
diff -u $1/.sha256sums.expected $1/.sha256sums.current || true
|
||||
exit 98
|
||||
fi
|
||||
}
|
||||
|
||||
testsuite_use_canonicalized=1
|
||||
testsuite_run_compress() {
|
||||
testsuite_header $testdir
|
||||
local files f
|
||||
if [[ $testsuite_use_canonicalized == 1 ]]; then
|
||||
files=t020_canonicalized/*/*
|
||||
else
|
||||
files=t010_decompressed/*/*
|
||||
fi
|
||||
for f in $files; do
|
||||
testsuite_split_f $f
|
||||
[[ -z $fb ]] && continue
|
||||
echo "# $f"
|
||||
mkdir -p $testdir/$fsubdir $testdir/.decompressed/$fsubdir
|
||||
$upx_run -qq --prefer-ucl "$@" $f -o $testdir/$fsubdir/$fb
|
||||
$upx_run -qq -d $testdir/$fsubdir/$fb -o $testdir/.decompressed/$fsubdir/$fb
|
||||
done
|
||||
testsuite_check_sha $testdir
|
||||
$upx_run -qq -l $testdir/*/*
|
||||
$upx_run -qq --file-info $testdir/*/*
|
||||
$upx_run -q -t $testdir/*/*
|
||||
if [[ $testsuite_use_canonicalized == 1 ]]; then
|
||||
# check that after decompression the file matches the canonicalized version
|
||||
cp t020_canonicalized/.sha256sums.expected $testdir/.decompressed/
|
||||
testsuite_check_sha_decompressed $testdir/.decompressed
|
||||
rm -rf "./$testdir/.decompressed"
|
||||
fi
|
||||
}
|
||||
|
||||
# /***********************************************************************
|
||||
# // expected checksums
|
||||
# //
|
||||
# // To ease maintenance of this script in case of updates this section
|
||||
# // can be automatically re-created from the current checksums -
|
||||
# // see call of function recreate_expected_sha256sums below.
|
||||
# ************************************************************************/
|
||||
|
||||
recreate_expected_sha256sums() {
|
||||
local o=$1
|
||||
local files f d
|
||||
echo "########## begin .sha256sums.recreate" > "$o"
|
||||
files=*/.sha256sums.current
|
||||
for f in $files; do
|
||||
d=$(dirname "$f")
|
||||
echo "expected_sha256sums__${d}="'"\' >> "$o"
|
||||
cat "$f" >> "$o"
|
||||
echo '"' >> "$o"
|
||||
done
|
||||
echo "########## end .sha256sums.recreate" >> "$o"
|
||||
}
|
||||
|
||||
source "$argv0dir/travis_testsuite_1-expected_sha256sums.sh" || exit 1
|
||||
|
||||
# /***********************************************************************
|
||||
# // init
|
||||
# ************************************************************************/
|
||||
|
||||
#set -x # debug
|
||||
exit_code=0
|
||||
num_errors=0
|
||||
all_errors=
|
||||
|
||||
if [[ $BM_T =~ (^|\+)ALLOW_FAIL($|\+) ]]; then
|
||||
echo "ALLOW_FAIL"
|
||||
set +e
|
||||
fi
|
||||
|
||||
if [[ -z $upx_exe ]]; then exit 1; fi
|
||||
upx_run=$upx_exe
|
||||
if [[ $BM_T =~ (^|\+)qemu($|\+) && -n $upx_qemu ]]; then
|
||||
upx_run="$upx_qemu $upx_qemu_flags -- $upx_exe"
|
||||
fi
|
||||
if [[ $BM_T =~ (^|\+)wine($|\+) && -n $upx_wine ]]; then
|
||||
upx_run="$upx_wine $upx_wine_flags $upx_exe"
|
||||
fi
|
||||
if [[ $BM_T =~ (^|\+)valgrind($|\+) ]]; then
|
||||
if [[ -z $upx_valgrind ]]; then
|
||||
upx_valgrind="valgrind"
|
||||
fi
|
||||
if [[ -z $upx_valgrind_flags ]]; then
|
||||
#upx_valgrind_flags="--leak-check=full --show-reachable=yes"
|
||||
#upx_valgrind_flags="-q --leak-check=no --error-exitcode=1"
|
||||
upx_valgrind_flags="--leak-check=no --error-exitcode=1"
|
||||
fi
|
||||
upx_run="$upx_valgrind $upx_valgrind_flags $upx_exe"
|
||||
fi
|
||||
|
||||
export UPX="--prefer-ucl --no-color --no-progress"
|
||||
export UPX_DEBUG_DISABLE_GITREV_WARNING=1
|
||||
export UPX_DEBUG_DOCTEST_VERBOSE=0
|
||||
|
||||
# let's go
|
||||
if ! $upx_run --version-short; then echo "UPX-ERROR: FATAL: upx --version-short FAILED"; exit 1; fi
|
||||
if ! $upx_run -L >/dev/null 2>&1; then echo "UPX-ERROR: FATAL: upx -L FAILED"; exit 1; fi
|
||||
if ! $upx_run --help >/dev/null; then echo "UPX-ERROR: FATAL: upx --help FAILED"; exit 1; fi
|
||||
rm -rf ./testsuite_1
|
||||
mkdir testsuite_1
|
||||
cd testsuite_1 || exit 1
|
||||
|
||||
# /***********************************************************************
|
||||
# // decompression tests
|
||||
# ************************************************************************/
|
||||
|
||||
testdir=t010_decompressed
|
||||
mkdir $testdir; v=expected_sha256sums__$testdir; echo -n "${!v}" >$testdir/.sha256sums.expected
|
||||
|
||||
testsuite_header $testdir
|
||||
for f in $upx_testsuite_SRCDIR/files/packed/*/upx-3.9[15]*; do
|
||||
testsuite_split_f $f
|
||||
[[ -z $fb ]] && continue
|
||||
echo "# $f"
|
||||
mkdir -p $testdir/$fsubdir
|
||||
$upx_run -qq -d $f -o $testdir/$fsubdir/$fb
|
||||
done
|
||||
testsuite_check_sha $testdir
|
||||
|
||||
# run one pack+unpack step to canonicalize the files
|
||||
testdir=t020_canonicalized
|
||||
mkdir $testdir; v=expected_sha256sums__$testdir; echo -n "${!v}" >$testdir/.sha256sums.expected
|
||||
|
||||
testsuite_header $testdir
|
||||
for f in t010_decompressed/*/*; do
|
||||
testsuite_split_f $f
|
||||
[[ -z $fb ]] && continue
|
||||
echo "# $f"
|
||||
mkdir -p $testdir/$fsubdir/.packed
|
||||
$upx_run -qq --prefer-ucl -1 $f -o $testdir/$fsubdir/.packed/$fb
|
||||
$upx_run -qq -d $testdir/$fsubdir/.packed/$fb -o $testdir/$fsubdir/$fb
|
||||
done
|
||||
testsuite_check_sha $testdir
|
||||
|
||||
# /***********************************************************************
|
||||
# // compression tests
|
||||
# // info: we use fast compression levels because we want to
|
||||
# // test UPX and not the compression libraries
|
||||
# ************************************************************************/
|
||||
|
||||
case $UPX_TESTSUITE_FAST in
|
||||
[0-7]) ;;
|
||||
*) UPX_TESTSUITE_FAST=999 ;;
|
||||
esac
|
||||
|
||||
if [[ $UPX_TESTSUITE_FAST -ge 1 ]]; then
|
||||
testdir=t110_compress_ucl_nrv2b_3_no_filter
|
||||
mkdir $testdir; v=expected_sha256sums__$testdir; echo -n "${!v}" >$testdir/.sha256sums.expected
|
||||
time testsuite_run_compress --nrv2b -3 --no-filter
|
||||
fi
|
||||
|
||||
if [[ $UPX_TESTSUITE_FAST -ge 2 ]]; then
|
||||
testdir=t120_compress_ucl_nrv2d_3_no_filter
|
||||
mkdir $testdir; v=expected_sha256sums__$testdir; echo -n "${!v}" >$testdir/.sha256sums.expected
|
||||
time testsuite_run_compress --nrv2d -3 --no-filter
|
||||
fi
|
||||
|
||||
if [[ $UPX_TESTSUITE_FAST -ge 3 ]]; then
|
||||
testdir=t130_compress_ucl_nrv2e_3_no_filter
|
||||
mkdir $testdir; v=expected_sha256sums__$testdir; echo -n "${!v}" >$testdir/.sha256sums.expected
|
||||
time testsuite_run_compress --nrv2e -3 --no-filter
|
||||
fi
|
||||
|
||||
if [[ $UPX_TESTSUITE_FAST -ge 4 ]]; then
|
||||
testdir=t140_compress_lzma_2_no_filter
|
||||
mkdir $testdir; v=expected_sha256sums__$testdir; echo -n "${!v}" >$testdir/.sha256sums.expected
|
||||
time testsuite_run_compress --lzma -2 --no-filter
|
||||
fi
|
||||
|
||||
if [[ $UPX_TESTSUITE_FAST -ge 5 ]]; then
|
||||
testdir=t150_compress_ucl_2_all_filters
|
||||
mkdir $testdir; v=expected_sha256sums__$testdir; echo -n "${!v}" >$testdir/.sha256sums.expected
|
||||
time testsuite_run_compress -2 --all-filters
|
||||
fi
|
||||
|
||||
if [[ $UPX_TESTSUITE_FAST -ge 6 ]]; then
|
||||
testdir=t160_compress_all_methods_1_no_filter
|
||||
mkdir $testdir; v=expected_sha256sums__$testdir; echo -n "${!v}" >$testdir/.sha256sums.expected
|
||||
time testsuite_run_compress --all-methods -1 --no-filter
|
||||
fi
|
||||
|
||||
if [[ $UPX_TESTSUITE_FAST -ge 7 ]]; then
|
||||
testdir=t170_compress_all_methods_no_lzma_5_no_filter
|
||||
mkdir $testdir; v=expected_sha256sums__$testdir; echo -n "${!v}" >$testdir/.sha256sums.expected
|
||||
time testsuite_run_compress --all-methods --no-lzma -5 --no-filter
|
||||
fi
|
||||
|
||||
# /***********************************************************************
|
||||
# // summary
|
||||
# ************************************************************************/
|
||||
|
||||
# recreate checksums from current version for an easy update in case of changes
|
||||
recreate_expected_sha256sums .sha256sums.recreate
|
||||
|
||||
testsuite_header "UPX testsuite summary"
|
||||
if ! $upx_run --version-short; then
|
||||
echo "UPX-ERROR: upx --version-short FAILED"
|
||||
exit 1
|
||||
fi
|
||||
echo
|
||||
echo "upx_exe='$upx_exe'"
|
||||
if [[ $upx_run != "$upx_exe" ]]; then
|
||||
echo "upx_run='$upx_run'"
|
||||
fi
|
||||
if [[ -f $upx_exe ]]; then
|
||||
ls -l "$upx_exe"
|
||||
file "$upx_exe" || true
|
||||
fi
|
||||
echo "upx_testsuite_SRCDIR='$upx_testsuite_SRCDIR'"
|
||||
echo "upx_testsuite_BUILDDIR='$upx_testsuite_BUILDDIR'"
|
||||
echo ".sha256sums.{expected,current}:"
|
||||
cat */.sha256sums.expected | LC_ALL=C sort | wc
|
||||
cat */.sha256sums.current | LC_ALL=C sort | wc
|
||||
echo
|
||||
if [[ $exit_code == 0 ]]; then
|
||||
echo "UPX testsuite passed. All done."
|
||||
else
|
||||
echo "UPX-ERROR: UPX testsuite FAILED:${all_errors}"
|
||||
echo "UPX-ERROR: UPX testsuite FAILED with $num_errors error(s). See log file."
|
||||
fi
|
||||
exit $exit_code
|
||||
@@ -0,0 +1,437 @@
|
||||
# Support for GitHub Actions -- https://github.com/features/actions
|
||||
|
||||
# note: GitHub Actions runner images are frequently updated, and
|
||||
# unfortunately this sometimes breaks builds in mysterious ways...
|
||||
# see https://github.com/actions/runner-images.git
|
||||
|
||||
name: 'CI'
|
||||
|
||||
on: [push, workflow_dispatch]
|
||||
|
||||
env:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
UPX_CMAKE_BUILD_FLAGS: --verbose
|
||||
|
||||
jobs:
|
||||
job-rebuild-and-verify-stubs:
|
||||
name: 'Rebuild stubs'
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: 'Install extra packages'
|
||||
run: |
|
||||
uname -a; pwd; id; umask
|
||||
mkdir ../deps; cd ../deps; mkdir packages
|
||||
# for ubuntu-22.04: install python2-minimal
|
||||
##sudo apt-get update && sudo apt-get install -y --no-install-recommends python2-minimal
|
||||
# manually install compat libs from Ubuntu 16.04
|
||||
wget -q 'http://archive.kernel.org/ubuntu-archive/ubuntu/pool/main/m/mpfr4/libmpfr4_3.1.6-1_amd64.deb'
|
||||
for f in ./*.deb; do dpkg -x $f ./packages; done
|
||||
sudo mv -v -n ./packages/usr/lib/x86_64-linux-gnu/lib* /usr/lib/x86_64-linux-gnu/
|
||||
rm -rf ./*.deb ./packages
|
||||
sudo ldconfig
|
||||
wget -q -O - https://github.com/upx/upx-stubtools/releases/download/v20221212/bin-upx-20221212.tar.xz | tar -xJ
|
||||
- name: 'Check out code'
|
||||
uses: actions/checkout@v3
|
||||
with: { submodules: true }
|
||||
- name: 'Rebuild and verify stubs'
|
||||
run: |
|
||||
export PATH="$(readlink -en ../deps/bin-upx-20221212):$PATH"
|
||||
make -C src/stub maintainer-clean extra-clean
|
||||
git status || true
|
||||
make -C src/stub extra-all all
|
||||
if ! git diff --quiet; then git diff; exit 1; fi
|
||||
- name: 'Check source code formatting'
|
||||
run: |
|
||||
bash ./misc/scripts/check_whitespace_git.sh
|
||||
UPX_CLANG_FORMAT="$PWD/../deps/bin-upx-20221212/clang-format-15.0.6" make -C src clang-format
|
||||
if ! git diff --quiet; then git diff; exit 1; fi
|
||||
|
||||
job-linux-cmake:
|
||||
needs: [ job-rebuild-and-verify-stubs ]
|
||||
name: ${{ format('{0} cmake', matrix.os) }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- { os: ubuntu-22.04, use_m32: true }
|
||||
- { os: ubuntu-20.04, use_m32: false }
|
||||
steps:
|
||||
- name: 'Install extra 32-bit and Windows packages'
|
||||
if: ${{ matrix.use_m32 }}
|
||||
run: |
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y g++-multilib g++-mingw-w64-i686 g++-mingw-w64-x86-64
|
||||
- name: 'Check out code'
|
||||
uses: actions/checkout@v3
|
||||
with: { submodules: true }
|
||||
- name: 'Check out test suite'
|
||||
run: 'git clone --depth=1 https://github.com/upx/upx-testsuite ../deps/upx-testsuite'
|
||||
- name: 'Build cmake extra/gcc/debug'
|
||||
run: 'make build/extra/gcc/debug'
|
||||
- name: 'Build cmake extra/gcc/release'
|
||||
run: 'make build/extra/gcc/release'
|
||||
- name: 'Build cmake extra/clang/debug'
|
||||
run: 'make build/extra/clang/debug'
|
||||
- name: 'Build cmake extra/clang/release'
|
||||
run: 'make build/extra/clang/release'
|
||||
- name: 'Build cmake extra/gcc-m32/debug'
|
||||
if: ${{ matrix.use_m32 }}
|
||||
run: 'make build/extra/gcc-m32/debug'
|
||||
- name: 'Build cmake extra/gcc-m32/release'
|
||||
if: ${{ matrix.use_m32 }}
|
||||
run: 'make build/extra/gcc-m32/release'
|
||||
- name: 'Build cmake extra/cross-windows-mingw32/release'
|
||||
if: ${{ matrix.use_m32 }}
|
||||
run: 'make build/extra/cross-windows-mingw32/release'
|
||||
- name: 'Build cmake extra/cross-windows-mingw64/release'
|
||||
if: ${{ matrix.use_m32 }}
|
||||
run: 'make build/extra/cross-windows-mingw64/release'
|
||||
- name: 'Make artifact'
|
||||
run: |
|
||||
N=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-${{ matrix.os }}
|
||||
mkdir -p "tmp/artifact/$N"
|
||||
(cd build && shopt -s nullglob && cp -ai --parents */upx{,.exe} */*/*/upx{,.exe} "../tmp/artifact/$N")
|
||||
(cd tmp/artifact && tar --sort=name -czf "$N.tar.gz" "$N" && rm -rf "./$N")
|
||||
# GitHub Actions magic: set "artifact_name" environment value for use in next step
|
||||
echo "artifact_name=$N" >> $GITHUB_ENV
|
||||
- name: ${{ format('Upload artifact {0}', env.artifact_name) }}
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ env.artifact_name }}
|
||||
path: tmp/artifact
|
||||
- name: 'Run basic tests'
|
||||
run: |
|
||||
make -C build/extra/gcc/debug test
|
||||
make -C build/extra/gcc/release test
|
||||
make -C build/extra/clang/debug test
|
||||
make -C build/extra/clang/release test
|
||||
- name: 'Run basic tests 32-bit'
|
||||
if: ${{ matrix.use_m32 }}
|
||||
run: |
|
||||
make -C build/extra/gcc-m32/debug test
|
||||
make -C build/extra/gcc-m32/release test
|
||||
- name: 'Run test suite build/extra/gcc/release'
|
||||
run: |
|
||||
export upx_testsuite_SRCDIR="$(readlink -en ../deps/upx-testsuite)"
|
||||
testsuite_1=$(readlink -en ./.github/travis_testsuite_1.sh)
|
||||
env -C build/extra/gcc/release upx_exe=./upx bash "$testsuite_1"
|
||||
|
||||
job-macos-cmake:
|
||||
needs: [ job-rebuild-and-verify-stubs ]
|
||||
name: ${{ format('{0} cmake', matrix.os) }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- { os: macos-11, gcc: gcc-10, gxx: 'g++-10', testsuite: true }
|
||||
- { os: macos-12, gcc: gcc-11, gxx: 'g++-11', testsuite: true }
|
||||
steps:
|
||||
- name: 'Install brew packages'
|
||||
if: ${{ matrix.testsuite }}
|
||||
run: |
|
||||
brew update
|
||||
brew install coreutils
|
||||
- name: 'Check out code'
|
||||
uses: actions/checkout@v3
|
||||
with: { submodules: true }
|
||||
- name: 'Check out test suite'
|
||||
if: ${{ matrix.testsuite }}
|
||||
run: 'git clone --depth=1 https://github.com/upx/upx-testsuite ../deps/upx-testsuite'
|
||||
- name: 'Build cmake extra/clang/debug'
|
||||
run: 'make build/extra/clang/debug'
|
||||
- name: 'Build cmake extra/clang/release'
|
||||
run: 'make build/extra/clang/release'
|
||||
- name: 'Build cmake extra/gcc/debug'
|
||||
if: ${{ matrix.gcc != '' }}
|
||||
run: 'make build/extra/gcc/debug CC=${{ matrix.gcc }} CXX=${{ matrix.gxx }}'
|
||||
- name: 'Build cmake extra/gcc/release'
|
||||
if: ${{ matrix.gcc != '' }}
|
||||
run: 'make build/extra/gcc/release CC=${{ matrix.gcc }} CXX=${{ matrix.gxx }}'
|
||||
- name: 'Build cmake xtarget/cross-darwin-arm64/debug'
|
||||
run: |
|
||||
CC="clang -target arm64-apple-darwin" CXX="clang++ -target arm64-apple-darwin" \
|
||||
make UPX_XTARGET=cross-darwin-arm64 xtarget/debug
|
||||
- name: 'Build cmake xtarget/cross-darwin-arm64/release'
|
||||
run: |
|
||||
CC="clang -target arm64-apple-darwin" CXX="clang++ -target arm64-apple-darwin" \
|
||||
make UPX_XTARGET=cross-darwin-arm64 xtarget/release
|
||||
- name: 'Make artifact'
|
||||
run: |
|
||||
N=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-${{ matrix.os }}
|
||||
mkdir -p "tmp/artifact/$N"
|
||||
(cd build && rsync -R -a */*/*/upx "../tmp/artifact/$N/")
|
||||
(cd tmp/artifact && gtar --sort=name -czf "$N.tar.gz" "$N" && rm -rf "./$N")
|
||||
# GitHub Actions magic: set "artifact_name" environment value for use in next step
|
||||
echo "artifact_name=$N" >> $GITHUB_ENV
|
||||
- name: ${{ format('Upload artifact {0}', env.artifact_name) }}
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ env.artifact_name }}
|
||||
path: tmp/artifact
|
||||
- name: 'Run basic tests'
|
||||
run: |
|
||||
make -C build/extra/clang/debug test
|
||||
make -C build/extra/clang/release test
|
||||
- name: 'Run test suite build/extra/clang/release'
|
||||
if: ${{ matrix.testsuite }}
|
||||
run: |
|
||||
export PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"
|
||||
export upx_testsuite_SRCDIR="$(readlink -en ../deps/upx-testsuite)"
|
||||
testsuite_1=$(readlink -en ./.github/travis_testsuite_1.sh)
|
||||
env -C build/extra/clang/release upx_exe=./upx bash "$testsuite_1"
|
||||
|
||||
job-windows-cmake:
|
||||
needs: [ job-rebuild-and-verify-stubs ]
|
||||
name: ${{ format('{0} cmake', matrix.os) }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# windows-2019 used to work but got broken with the 20220821.1 runner-image
|
||||
# update; we cannot download that image for inspection, and debugging the
|
||||
# remote image is painful, so disable for now
|
||||
# see https://github.com/actions/runner-images.git
|
||||
####- { os: windows-2019 }
|
||||
- { os: windows-2022 }
|
||||
steps:
|
||||
- name: 'Check out code'
|
||||
uses: actions/checkout@v3
|
||||
with: { submodules: true }
|
||||
- name: 'Check out test suite'
|
||||
run: 'git clone --depth=1 https://github.com/upx/upx-testsuite ../deps/upx-testsuite'
|
||||
- name: 'Inspect runner-image settings'
|
||||
# debug remote image; also see https://github.com/actions/runner-images.git
|
||||
if: ${{ false }}
|
||||
run: |
|
||||
Get-Command bash; Get-Command cmake; Get-Command make
|
||||
bash --version; cmake --version; make --version
|
||||
Get-Command cl -ErrorAction SilentlyContinue
|
||||
- name: 'Build cmake debug'
|
||||
run: 'make build/debug'
|
||||
- name: 'Build cmake release'
|
||||
run: 'make build/release'
|
||||
- name: 'Make artifact'
|
||||
shell: bash
|
||||
run: |
|
||||
N=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-${{ matrix.os }}
|
||||
mkdir -p "tmp/artifact/$N"
|
||||
(cd build && cp -ai --parents */*/upx.exe "../tmp/artifact/$N")
|
||||
# GitHub Actions magic: set "artifact_name" environment value for use in next step
|
||||
echo "artifact_name=$N" >> $GITHUB_ENV
|
||||
- name: ${{ format('Upload artifact {0}', env.artifact_name) }}
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ env.artifact_name }}
|
||||
path: tmp/artifact
|
||||
- name: 'Run basic tests'
|
||||
run: |
|
||||
cmake --build build/debug --config Debug --target RUN_TESTS
|
||||
cmake --build build/release --config Release --target RUN_TESTS
|
||||
- name: 'Run test suite build/release'
|
||||
shell: bash
|
||||
run: |
|
||||
export upx_testsuite_SRCDIR="$(readlink -en ../deps/upx-testsuite)"
|
||||
testsuite_1=$(readlink -en ./.github/travis_testsuite_1.sh)
|
||||
env -C build/release/Release upx_exe=./upx bash "$testsuite_1"
|
||||
|
||||
job-windows-toolchains:
|
||||
needs: [ job-rebuild-and-verify-stubs ]
|
||||
name: ${{ format('windows {0}', matrix.name) }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
C: ${{ matrix.C }}
|
||||
B: release
|
||||
H: 'd:\a\upx\upx'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- { name: amd64-win64-vs2019, os: windows-2019, C: msvc-14.2-x64, arch: amd64 }
|
||||
- { name: amd64-win64-vs2022, os: windows-2022, C: msvc-14.3-x64, arch: amd64 }
|
||||
- { name: arm64-win64-vs2019, os: windows-2019, C: msvc-14.2-x64, arch: amd64_arm64 }
|
||||
- { name: arm64-win64-vs2022, os: windows-2022, C: msvc-14.3-x64, arch: amd64_arm64 }
|
||||
- { name: i386-win32-vs2019, os: windows-2019, C: msvc-14.2-x86, arch: amd64_x86 }
|
||||
- { name: i386-win32-vs2022, os: windows-2022, C: msvc-14.3-x86, arch: amd64_x86 }
|
||||
steps:
|
||||
- name: 'Check out code'
|
||||
uses: actions/checkout@v3
|
||||
with: { submodules: true }
|
||||
- name: 'Prepare sources and Check out test suite'
|
||||
shell: bash
|
||||
run: |
|
||||
git config --global core.autocrlf input
|
||||
git --version && bash --version
|
||||
git clone --depth=1 https://github.com/upx/upx-testsuite ../deps/upx-testsuite
|
||||
mkdir -p -v build/$C/$B/{ucl,upx,zlib,zstd}
|
||||
- name: 'Set up Developer Command Prompt'
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: ${{ matrix.arch }}
|
||||
- name: 'Build'
|
||||
shell: cmd
|
||||
run: |
|
||||
@REM setup directories
|
||||
where cl & where link
|
||||
set BDIR=%H%\build\%C%\%B%
|
||||
set DEFS=-D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS
|
||||
git rev-parse --short=12 HEAD > %BDIR%\upx\.GITREV.txt
|
||||
@REM ===== build UCL =====
|
||||
cd %BDIR%\ucl
|
||||
set s=%H%\vendor\ucl
|
||||
cl -MT -J -O2 -W4 -WX %DEFS% -I%s%\include -I%s% -c %s%\src\*.c
|
||||
link -lib -out:ucl.lib *.obj
|
||||
@REM ===== build zlib =====
|
||||
cd %BDIR%\zlib
|
||||
cl -MT -J -O2 -W3 -WX %DEFS% -c %H%\vendor\zlib\*.c
|
||||
link -lib -out:zlib.lib *.obj
|
||||
@REM ===== build zstd =====
|
||||
@rem cd %BDIR%\zstd
|
||||
@rem set s=%H%\vendor\zstd\lib
|
||||
@rem cl -MT -J -O2 -W4 -WX -DDYNAMIC_BMI2=0 -DZSTD_DISABLE_ASM %DEFS% -c %s%\common\*.c %s%\compress\*.c %s%\decompress\*.c
|
||||
@rem link -lib -out:zstd.lib *.obj
|
||||
@REM ===== build UPX =====
|
||||
cd %BDIR%\upx
|
||||
set s=%H%\src
|
||||
cat .GITREV.txt
|
||||
set /p GITREV=<.GITREV.txt
|
||||
set sources=%s%\*.cpp %s%\check\*.cpp %s%\compress\*.cpp %s%\console\*.cpp %s%\filter\*.cpp %s%\util\*.cpp
|
||||
cl -MT -std:c++17 -Zc:__cplusplus -EHsc -J -O2 -W4 -WX -DUPX_VERSION_GITREV="""%GITREV%""" -DWITH_ZSTD=0 %DEFS% -I%H%\vendor -I%H%\vendor\boost-pfr\include -Feupx.exe %sources% %BDIR%\ucl\ucl.lib %BDIR%\zlib\zlib.lib /link setargv.obj
|
||||
- name: 'Make artifact'
|
||||
shell: bash
|
||||
run: |
|
||||
N=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-windows-${{ matrix.name }}
|
||||
mkdir -p "tmp/artifact/$N/$B"
|
||||
cp -ai build/$C/$B/upx/upx*.exe "tmp/artifact/$N/$B"
|
||||
# GitHub Actions magic: set "artifact_name" environment value for use in next step
|
||||
echo "artifact_name=$N" >> $GITHUB_ENV
|
||||
- name: ${{ format('Upload artifact {0}', env.artifact_name) }}
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ env.artifact_name }}
|
||||
path: tmp/artifact
|
||||
- name: 'Run basic tests'
|
||||
if: ${{ matrix.arch != 'amd64_arm64' }}
|
||||
run: |
|
||||
$ErrorActionPreference = 'stop'
|
||||
$ErrorView = 'NormalView'
|
||||
cd $Env:H\build\$Env:C\$Env:B\upx
|
||||
$Env:UPX = "--no-color --no-progress"
|
||||
.\upx.exe --version
|
||||
.\upx.exe upx.exe -o upx_packed.exe
|
||||
dir *.exe
|
||||
.\upx.exe -l upx_packed.exe
|
||||
.\upx.exe -t upx_packed.exe
|
||||
.\upx_packed.exe --version
|
||||
- name: 'Run test suite'
|
||||
if: ${{ matrix.arch != 'amd64_arm64' }}
|
||||
shell: bash
|
||||
run: |
|
||||
export upx_testsuite_SRCDIR="$(readlink -en ../deps/upx-testsuite)"
|
||||
testsuite_1=$(readlink -en ./.github/travis_testsuite_1.sh)
|
||||
env -C build/$C/$B/upx upx_exe=./upx.exe bash "$testsuite_1"
|
||||
|
||||
job-linux-zigcc:
|
||||
if: ${{ true }}
|
||||
needs: [ job-rebuild-and-verify-stubs ]
|
||||
name: ${{ format('zigcc {0} {1}', matrix.zig_target, matrix.zig_pic) }}
|
||||
runs-on: ubuntu-latest
|
||||
##container: alpine:3.17 # older versions such as alpine:3.12 also work; no-container also works
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- { zig_target: aarch64-linux-musl }
|
||||
- { zig_target: aarch64-macos.11-none }
|
||||
- { zig_target: aarch64-macos.12-none }
|
||||
- { zig_target: aarch64-macos.13-none }
|
||||
- { zig_target: aarch64-windows-gnu }
|
||||
- { zig_target: i386-linux-musl }
|
||||
- { zig_target: i386-windows-gnu }
|
||||
- { zig_target: x86_64-linux-musl }
|
||||
- { zig_target: x86_64-linux-musl, zig_pic: -fPIE }
|
||||
- { zig_target: x86_64-macos.11-none }
|
||||
- { zig_target: x86_64-macos.12-none }
|
||||
- { zig_target: x86_64-macos.13-none }
|
||||
- { zig_target: x86_64-windows-gnu }
|
||||
env:
|
||||
# 2023-01-30
|
||||
ZIG_DIST_VERSION: 0.11.0-dev.1491+2b27bc2c6
|
||||
# for zig-cc wrapper scripts (see below):
|
||||
ZIG_CPPFLAGS: -DUPX_DOCTEST_CONFIG_MULTITHREADING
|
||||
ZIG_FLAGS: ${{ matrix.zig_flags }}
|
||||
ZIG_PIC: ${{ matrix.zig_pic }}
|
||||
ZIG_TARGET: ${{ matrix.zig_target }}
|
||||
steps:
|
||||
- name: 'Install Alpine Linux container packages'
|
||||
if: ${{ job.container }}
|
||||
shell: sh
|
||||
run: |
|
||||
apk update && apk upgrade && apk add bash cmake file git make tar xz
|
||||
# set PATH like in Ubuntu
|
||||
echo "PATH=$HOME/.local/bin:$PATH" >> $GITHUB_ENV
|
||||
# this seems to be needed when running in a container (beause of UID mismatch??)
|
||||
git config --global --add safe.directory '*'
|
||||
- name: 'Check out code'
|
||||
uses: actions/checkout@v3
|
||||
with: { submodules: true }
|
||||
- name: ${{ format('Install Zig {0}', env.ZIG_DIST_VERSION) }}
|
||||
shell: bash
|
||||
run: |
|
||||
# GitHub Actions magic: set "UPX_GITREV_SHORT" environment value for use in steps below
|
||||
rev=$(git rev-parse --short=7 HEAD)
|
||||
echo "UPX_GITREV_SHORT=$rev" >> $GITHUB_ENV
|
||||
# update ZIG_TARGET (i386 => x86)
|
||||
ZIG_TARGET=${ZIG_TARGET/i386-/x86-}
|
||||
echo "ZIG_TARGET=$ZIG_TARGET" >> $GITHUB_ENV
|
||||
# install zig; note that ~/.local/bin is included in the default $PATH on Ubuntu
|
||||
mkdir -p -v ~/.local/bin
|
||||
cd ~/.local/bin
|
||||
ZIG_DIST_NAME=zig-linux-x86_64-${ZIG_DIST_VERSION}
|
||||
wget -q 'https://ziglang.org/builds/'${ZIG_DIST_NAME}.tar.xz
|
||||
ls -l ${ZIG_DIST_NAME}.tar.xz
|
||||
tar -xoJf ${ZIG_DIST_NAME}.tar.xz
|
||||
rm ${ZIG_DIST_NAME}.tar.xz
|
||||
ln -s -v ${ZIG_DIST_NAME}/zig zig
|
||||
#echo "PATH=$PATH" && which zig
|
||||
echo -n 'zig version: '; zig version
|
||||
# create wrapper scripts (needed for CMake)
|
||||
echo -e '#!/bin/sh\nexec zig ar "$@"' > zig-ar
|
||||
echo -e '#!/bin/sh\nexec zig cc -target $ZIG_TARGET $ZIG_PIC $ZIG_FLAGS $ZIG_CPPFLAGS $ZIG_CFLAGS "$@"' > zig-cc
|
||||
echo -e '#!/bin/sh\nexec zig c++ -target $ZIG_TARGET $ZIG_PIC $ZIG_FLAGS $ZIG_CPPFLAGS $ZIG_CXXFLAGS "$@"' > zig-cxx
|
||||
echo -e '#!/bin/sh\nexec zig ranlib "$@"' > zig-ranlib
|
||||
chmod +x zig-ar zig-cc zig-cxx zig-ranlib
|
||||
ls -la; head zig-ar zig-cc zig-cxx zig-ranlib
|
||||
- name: ${{ format('Build Release with zig-cc -target {0} {1}', env.ZIG_TARGET, env.ZIG_PIC) }}
|
||||
run: |
|
||||
mkdir -p build/zig/${ZIG_TARGET}${ZIG_PIC}/release
|
||||
cd build/zig/${ZIG_TARGET}${ZIG_PIC}/release
|
||||
cmake ../../../.. -DCMAKE_BUILD_TYPE=Release -DCMAKE_AR=$HOME/.local/bin/zig-ar -DCMAKE_C_COMPILER=zig-cc -DCMAKE_CXX_COMPILER=zig-cxx -DCMAKE_RANLIB=$HOME/.local/bin/zig-ranlib $EXTRA_CMAKE_CONFIG_FLAGS_RELEASE
|
||||
cmake --build . --config Release --parallel --verbose
|
||||
file ./upx*
|
||||
- name: ${{ format('Build Debug with zig-cc -target {0} {1}', env.ZIG_TARGET, env.ZIG_PIC) }}
|
||||
run: |
|
||||
mkdir -p build/zig/${ZIG_TARGET}${ZIG_PIC}/debug
|
||||
cd build/zig/${ZIG_TARGET}${ZIG_PIC}/debug
|
||||
cmake ../../../.. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_AR=$HOME/.local/bin/zig-ar -DCMAKE_C_COMPILER=zig-cc -DCMAKE_CXX_COMPILER=zig-cxx -DCMAKE_RANLIB=$HOME/.local/bin/zig-ranlib $EXTRA_CMAKE_CONFIG_FLAGS_DEBUG
|
||||
cmake --build . --config Debug --parallel --verbose
|
||||
file ./upx*
|
||||
- name: ${{ format('Make artifact from upx-{0}-{1}', github.ref_name, env.UPX_GITREV_SHORT) }}
|
||||
shell: bash
|
||||
run: |
|
||||
N=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-zigcc-${{ matrix.zig_target }}${ZIG_PIC}
|
||||
mkdir -p "tmp/artifact/$N"
|
||||
(cd build && shopt -s nullglob && cp -ai --parents */upx{,.exe} */*/*/upx{,.exe} "../tmp/artifact/$N")
|
||||
(cd tmp/artifact && tar --sort=name -czf "$N.tar.gz" "$N" && rm -rf "./$N")
|
||||
# GitHub Actions magic: set "artifact_name" environment value for use in next step
|
||||
echo "artifact_name=$N" >> $GITHUB_ENV
|
||||
- name: ${{ format('Upload artifact {0}', env.artifact_name) }}
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ env.artifact_name }}
|
||||
path: tmp/artifact
|
||||
|
||||
# vim:set ts=2 sw=2 et:
|
||||
@@ -0,0 +1,37 @@
|
||||
# see https://docs.github.com/en/actions/managing-issues-and-pull-requests/closing-inactive-issues
|
||||
# see https://github.com/actions/stale
|
||||
|
||||
# Automatically closing issues is far from perfect, but then we only
|
||||
# have limited resources and this approach favors issues that people
|
||||
# actually care about.
|
||||
#
|
||||
# also see:
|
||||
# "Should I Stale or Should I Close? An Analysis of a Bot that Closes
|
||||
# Abandoned Issues and Pull Request".
|
||||
# https://igorwiese.com/images/papers/Paper_BotSE_19.pdf
|
||||
|
||||
name: 'GitHub - Close inactive issues'
|
||||
on:
|
||||
schedule:
|
||||
- cron: '30 6 * * 4'
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
close-issues:
|
||||
name: 'Close inactive issues'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/stale@v7
|
||||
with:
|
||||
operations-per-run: 300
|
||||
exempt-all-milestones: true
|
||||
exempt-issue-labels: 'blocker,enhancement,regression'
|
||||
days-before-stale: 60
|
||||
days-before-close: 30
|
||||
stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Please remove the stale label or add a comment or this issue will be closed in 30 days.'
|
||||
stale-pr-message: 'This PR is stale because it has been open 60 days with no activity. Please remove the stale label or add a comment or this PR will be closed in 30 days.'
|
||||
close-issue-message: 'This issue was closed because it has been stalled for 30 days with no activity. Please feel free to reopen.'
|
||||
close-pr-message: 'This PR was closed because it has been stalled for 30 days with no activity. Please feel free to reopen.'
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -0,0 +1,38 @@
|
||||
name: 'Static Analyzer - CodeQL'
|
||||
|
||||
on:
|
||||
# push:
|
||||
# branches: [ 'devel', 'devel4', 'devel5', 'master' ]
|
||||
# pull_request:
|
||||
# # The branches below must be a subset of the branches above
|
||||
# branches: [ 'devel', 'devel4', 'devel5' ]
|
||||
schedule:
|
||||
- cron: '20 1 * * 3'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'cpp' ]
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with: { submodules: true }
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
@@ -0,0 +1,29 @@
|
||||
# minimal GitHub CI building UPX with clang and gcc in an Alpine Linux container
|
||||
|
||||
name: 'CI - Minimal CI with Alpine Linux'
|
||||
|
||||
on: { workflow_dispatch: }
|
||||
jobs:
|
||||
job-alpine-cmake:
|
||||
strategy: {matrix: {container: ['alpine:3.12','alpine:3.17','alpine:edge']}}
|
||||
name: ${{ format('container {0}', matrix.container) }}
|
||||
runs-on: ubuntu-latest
|
||||
container: ${{ matrix.container }}
|
||||
steps:
|
||||
- name: ${{ format('Install packages {0}', matrix.container) }}
|
||||
run: 'apk update && apk upgrade && apk add bash clang cmake g++ git make'
|
||||
- name: ${{ format('Check out code upx-{0}', github.ref_name) }}
|
||||
run: |
|
||||
git clone --branch "$GITHUB_REF_NAME" --depth 1 https://github.com/upx/upx
|
||||
git -C upx submodule update --init
|
||||
echo "artifact_name=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-minimal-ci-${{ matrix.container }}" | sed 's/[:,; ]/-/g' >> $GITHUB_ENV
|
||||
- { name: 'Build clang', run: 'make -C upx UPX_XTARGET=clang-static CC="clang -static" CXX="clang++ -static"' }
|
||||
- { name: 'Build gcc', run: 'make -C upx UPX_XTARGET=gcc-static CC="gcc -static" CXX="g++ -static"' }
|
||||
- { name: 'Strip release binaries', run: 'strip -p --strip-unneeded upx/build/*/*/release/upx' }
|
||||
- name: ${{ format('Upload artifact {0}', env.artifact_name) }}
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ env.artifact_name }}
|
||||
path: 'upx*/build/*/*/*/upx'
|
||||
- { name: 'Run basic tests clang', run: 'make -C upx/build/xtarget/clang-static/release test' }
|
||||
- { name: 'Run basic tests gcc', run: 'make -C upx/build/xtarget/gcc-static/release test' }
|
||||
@@ -0,0 +1,16 @@
|
||||
name: 'GitHub - Close pull requests'
|
||||
on:
|
||||
#pull_request:
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
close-pull-requests:
|
||||
name: 'Close pull requests'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: 'Close pull requests'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
gh pr list --repo='${{ github.repository }}' --state=open --json=number | jq '.[].number' | xargs -r -n1 -- gh pr close --repo='${{ github.repository }}'
|
||||
@@ -0,0 +1,22 @@
|
||||
name: 'Static Analyzer - scan-build'
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '40 1 * * 3'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
container: 'alpine:edge'
|
||||
steps:
|
||||
- name: 'Install packages'
|
||||
run: 'apk update && apk upgrade && apk add bash clang clang-analyzer cmake g++ git make'
|
||||
- name: 'Check out code'
|
||||
uses: actions/checkout@v3
|
||||
with: { submodules: true }
|
||||
- name: 'Perform scan-build Analysis Debug'
|
||||
run: 'make build/extra/scan-build/debug'
|
||||
- name: 'Perform scan-build Analysis Release'
|
||||
run: 'make build/extra/scan-build/release'
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/.hg*
|
||||
/.vscode*
|
||||
/Makevars.global*
|
||||
/build*
|
||||
/maint*
|
||||
/vendor*
|
||||
|
||||
GNUmakefile
|
||||
MMakefile
|
||||
Makevars.local*
|
||||
tmp*
|
||||
|
||||
*.a
|
||||
*.d
|
||||
*.dll
|
||||
*.exe
|
||||
*.lib
|
||||
*.map
|
||||
*.o
|
||||
*.obj
|
||||
*.out
|
||||
*.py[cdo]
|
||||
*.so
|
||||
*.swp
|
||||
*.ttp
|
||||
|
||||
doc/*.man
|
||||
doc/*.ps
|
||||
doc/*.tex
|
||||
|
||||
src/stub/**/.*-stamp
|
||||
src/stub/tmp*/*.bin
|
||||
src/stub/tmp*/*.bin.bindump
|
||||
src/stub/tmp*/*.bin.disasm
|
||||
src/stub/tmp*/*.o.disasm
|
||||
src/stub/tmp*/mips.r3000-*.[is]
|
||||
src/stub/tmp*/mipsel.r3000-*.[is]
|
||||
src/stub/src/**/tmp*/*
|
||||
|
||||
src/stub/tools/sstrip/amd64-linux-sstrip
|
||||
src/stub/tools/sstrip/i386-linux-sstrip
|
||||
src/stub/tools/sstrip/sstrip
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
[submodule "vendor/doctest"]
|
||||
path = vendor/doctest
|
||||
url = https://github.com/upx/upx-vendor-doctest.git
|
||||
branch = upx-vendor
|
||||
shallow = true
|
||||
[submodule "vendor/lzma-sdk"]
|
||||
path = vendor/lzma-sdk
|
||||
url = https://github.com/upx/upx-vendor-lzma-sdk.git
|
||||
branch = upx-vendor
|
||||
shallow = true
|
||||
[submodule "vendor/ucl"]
|
||||
path = vendor/ucl
|
||||
url = https://github.com/upx/upx-vendor-ucl.git
|
||||
branch = upx-vendor
|
||||
shallow = true
|
||||
[submodule "vendor/valgrind"]
|
||||
path = vendor/valgrind
|
||||
url = https://github.com/upx/upx-vendor-valgrind.git
|
||||
branch = upx-vendor
|
||||
shallow = true
|
||||
[submodule "vendor/zlib"]
|
||||
path = vendor/zlib
|
||||
url = https://github.com/upx/upx-vendor-zlib.git
|
||||
branch = upx-vendor
|
||||
shallow = true
|
||||
@@ -1,52 +0,0 @@
|
||||
syntax: regexp
|
||||
|
||||
^\.bzr
|
||||
^ChangeLog
|
||||
^Makevars.global
|
||||
^build
|
||||
^maint
|
||||
|
||||
syntax: glob
|
||||
|
||||
.depend
|
||||
Makevars.local
|
||||
|
||||
*.a
|
||||
*.dll
|
||||
*.lib
|
||||
*.py[cdo]
|
||||
*.so
|
||||
*.swp
|
||||
|
||||
doc/*.1
|
||||
doc/*.doc
|
||||
doc/*.html
|
||||
doc/*.man
|
||||
doc/*.ps
|
||||
doc/*.tex
|
||||
|
||||
src/GNUmakefile
|
||||
src/MMakefile
|
||||
src/compress_nrv*
|
||||
src/*.mft
|
||||
src/*.rc
|
||||
|
||||
src/*.d
|
||||
src/*.exe
|
||||
src/*.map
|
||||
src/*.o
|
||||
src/*.obj
|
||||
src/*.out
|
||||
src/*.res
|
||||
src/*.ttp
|
||||
|
||||
stub/**MMakefile
|
||||
stub/**.*-stamp
|
||||
stub/tmp*/*
|
||||
stub/**/tmp*/*
|
||||
|
||||
stub/tools/armpe/armpe_tester
|
||||
|
||||
stub/tools/sstrip/amd64-linux-sstrip
|
||||
stub/tools/sstrip/i386-linux-sstrip
|
||||
stub/tools/sstrip/sstrip
|
||||
@@ -1,19 +0,0 @@
|
||||
140415ffbcef86a42b4d672249927364430d3d38 RELEASE_111
|
||||
1931f4f28074970ec53b4cd21c7fc181b4da8e5e RELEASE_301
|
||||
223ac5b23f9731ceac9ff8d65167df4900776e36 RELEASE_190
|
||||
2c753c5bf38e7322715e2a5c6c5381111bd7a61a RELEASE_194
|
||||
2ee65b77f9117651e2e5517b2edede23698d73ca RELEASE_196
|
||||
396983c065fc743cb5b9703e266ca87eeff8a6ee RELEASE_291
|
||||
46f3a6cca02603000fadc16637b02e30caddd909 RELEASE_302
|
||||
70402aeee6e0e4fc2889658ed8cee44461c0b0a8 RELEASE_200
|
||||
a1c61174f54aac714f59ac20fcba839d71e64c5c RELEASE_292
|
||||
a916a2fe22de45167d25abcb40008315f415221c RELEASE_201
|
||||
a935d577fc7dd9c2c87761c9c702805da6ce1e51 RELEASE_193
|
||||
b0353253b0b3d062eb5adb50d4b665a96620da45 RELEASE_195
|
||||
b82ef51896199484afe5b0553af7d1e59b7ce428 BRANCHPOINT_FOR_upx2.hg
|
||||
c2e0cd4d621b047f254f2def42132a03683ff52c RELEASE_192
|
||||
d276aa09033c24d0981bc3f4fee5628aecc988ad RELEASE_290
|
||||
eb1ce56dce7dd1835964362470610925963b9043 RELEASE_110
|
||||
ed96891ef795bceec6b7ff3ca1ca7764431bfb39 RELEASE_191
|
||||
ef9c7f2c9658d73a9b5ab2ed291483d2bbcd8bc7 RELEASE_300
|
||||
efa52753e366300c0e0ebe20631adcb24ed3c15b RELEASE_293
|
||||
+349
@@ -0,0 +1,349 @@
|
||||
cmake_minimum_required(VERSION 3.8.0 FATAL_ERROR)
|
||||
|
||||
# compilation config options
|
||||
if(NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git")
|
||||
# permissive config defaults when building from source code tarball
|
||||
option(UPX_CONFIG_DISABLE_GITREV "Do not compile with default Git version info." ON)
|
||||
option(UPX_CONFIG_DISABLE_SANITIZE "Do not compile with default sanitize options." ON)
|
||||
option(UPX_CONFIG_DISABLE_WERROR "Do not compile with default -Werror option." ON)
|
||||
else()
|
||||
# strict config defaults for devel builds
|
||||
message(STATUS "===== UPX info: strict config defaults enabled")
|
||||
option(UPX_CONFIG_DISABLE_GITREV "Do not compile with default Git version info." OFF)
|
||||
option(UPX_CONFIG_DISABLE_SANITIZE "Do not compile with default sanitize options." OFF)
|
||||
option(UPX_CONFIG_DISABLE_WERROR "Do not compile with default -Werror option." OFF)
|
||||
endif()
|
||||
|
||||
# test config options (see below)
|
||||
# NOTE: self-pack test can only work if the host executable format is supported by UPX!
|
||||
option(UPX_CONFIG_DISABLE_SELF_PACK_TEST "Do not test packing UPX with itself" OFF)
|
||||
|
||||
#***********************************************************************
|
||||
# init
|
||||
#***********************************************************************
|
||||
|
||||
# Disallow in-source builds. Note that you will still have to manually
|
||||
# clean up a few files if you accidentally try an in-source build.
|
||||
if(NOT MSVC_IDE)
|
||||
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
|
||||
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
|
||||
if(",${CMAKE_CURRENT_SOURCE_DIR}," STREQUAL ",${CMAKE_CURRENT_BINARY_DIR},")
|
||||
message(FATAL_ERROR "ERROR: In-source builds are not allowed, please use an extra build dir.")
|
||||
endif()
|
||||
endif()
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
# determine git revision
|
||||
set(GITREV_SHORT "")
|
||||
set(GITREV_PLUS "")
|
||||
set(GIT_DESCRIBE "")
|
||||
find_package(Git)
|
||||
if(Git_FOUND AND NOT UPX_CONFIG_DISABLE_GITREV)
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" rev-parse --short=12 HEAD
|
||||
RESULT_VARIABLE result ERROR_QUIET
|
||||
OUTPUT_VARIABLE GITREV_SHORT OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
string(LENGTH "${GITREV_SHORT}" l)
|
||||
if(${result} EQUAL 0 AND ${l} EQUAL 12)
|
||||
execute_process(RESULT_VARIABLE result COMMAND "${GIT_EXECUTABLE}" diff --quiet)
|
||||
if(NOT ${result} EQUAL 0)
|
||||
set(GITREV_PLUS "+")
|
||||
endif()
|
||||
else()
|
||||
set(GITREV_SHORT "")
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" describe --match "v*.*.*" --tags --dirty
|
||||
RESULT_VARIABLE result ERROR_QUIET
|
||||
OUTPUT_VARIABLE GIT_DESCRIBE OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
if(GIT_DESCRIBE MATCHES "^v?([0-9]+\\.[0-9]+\\.[0-9]+)-([0-9]+)-g(.+)$")
|
||||
set(GIT_DESCRIBE "${CMAKE_MATCH_1}-devel.${CMAKE_MATCH_2}+git-${CMAKE_MATCH_3}")
|
||||
endif()
|
||||
endif()
|
||||
if(NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git") # extra check
|
||||
set(GITREV_SHORT "")
|
||||
endif()
|
||||
if(GITREV_SHORT)
|
||||
message(STATUS "UPX_VERSION_GITREV = \"${GITREV_SHORT}${GITREV_PLUS}\"")
|
||||
if(GIT_DESCRIBE)
|
||||
message(STATUS "UPX_VERSION_GIT_DESCRIBE = \"${GIT_DESCRIBE}\"")
|
||||
endif()
|
||||
elseif(UPX_CONFIG_DISABLE_GITREV)
|
||||
message(STATUS "UPX_VERSION_GITREV: disabled")
|
||||
else()
|
||||
message(STATUS "UPX_VERSION_GITREV: not set")
|
||||
endif()
|
||||
|
||||
# CMake init
|
||||
project(upx VERSION 4.0.2 LANGUAGES C CXX)
|
||||
|
||||
# set default build type to "Release"
|
||||
get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
if(is_multi_config)
|
||||
set(c "${CMAKE_CONFIGURATION_TYPES}")
|
||||
list(INSERT c 0 "Release")
|
||||
list(INSERT c 1 "Debug")
|
||||
if (CMAKE_BUILD_TYPE)
|
||||
list(INSERT c 0 "${CMAKE_BUILD_TYPE}")
|
||||
endif()
|
||||
list(REMOVE_DUPLICATES c)
|
||||
set(CMAKE_CONFIGURATION_TYPES "${c}" CACHE STRING "List of supported configuration types." FORCE)
|
||||
elseif(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE)
|
||||
endif()
|
||||
|
||||
#***********************************************************************
|
||||
# targets and compilation flags
|
||||
#***********************************************************************
|
||||
|
||||
#find_package(Threads) # multithreading is currently not used; maybe in UPX version 5
|
||||
set(UPX_CONFIG_DISABLE_ZSTD ON) # zstd is currently not used; maybe in UPX version 5
|
||||
|
||||
file(GLOB ucl_SOURCES "vendor/ucl/src/*.c")
|
||||
list(SORT ucl_SOURCES)
|
||||
add_library(upx_vendor_ucl STATIC ${ucl_SOURCES})
|
||||
set_property(TARGET upx_vendor_ucl PROPERTY C_STANDARD 11)
|
||||
|
||||
file(GLOB zlib_SOURCES "vendor/zlib/*.c")
|
||||
list(SORT zlib_SOURCES)
|
||||
add_library(upx_vendor_zlib STATIC ${zlib_SOURCES})
|
||||
set_property(TARGET upx_vendor_zlib PROPERTY C_STANDARD 11)
|
||||
|
||||
if(NOT UPX_CONFIG_DISABLE_ZSTD)
|
||||
file(GLOB zstd_SOURCES "vendor/zstd/lib/*/*.c")
|
||||
list(SORT zstd_SOURCES)
|
||||
add_library(upx_vendor_zstd STATIC ${zstd_SOURCES})
|
||||
set_property(TARGET upx_vendor_zstd PROPERTY C_STANDARD 11)
|
||||
endif()
|
||||
|
||||
file(GLOB upx_SOURCES "src/*.cpp" "src/[cfu]*/*.cpp")
|
||||
list(SORT upx_SOURCES)
|
||||
add_executable(upx ${upx_SOURCES})
|
||||
set_property(TARGET upx PROPERTY CXX_STANDARD 17)
|
||||
target_link_libraries(upx upx_vendor_ucl upx_vendor_zlib)
|
||||
|
||||
if(NOT MSVC)
|
||||
# rather strict default compilation warnings
|
||||
set(warn_strict
|
||||
-Wall -Wextra -Wcast-align -Wcast-qual -Wmissing-declarations
|
||||
-Wpointer-arith -Wshadow -Wvla -Wwrite-strings
|
||||
)
|
||||
endif()
|
||||
if(UPX_CONFIG_DISABLE_WERROR)
|
||||
set(warn_Werror "")
|
||||
set(warn_WX "")
|
||||
else()
|
||||
set(warn_Werror -Werror)
|
||||
set(warn_WX -WX)
|
||||
endif()
|
||||
|
||||
if(NOT MSVC)
|
||||
# use -O2 instead of -O3 to reduce code size
|
||||
string(REGEX REPLACE "(^| )-O3( |$$)" "\\1-O2\\2" a "${CMAKE_C_FLAGS_RELEASE}")
|
||||
string(REGEX REPLACE "(^| )-O3( |$$)" "\\1-O2\\2" b "${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${a}" CACHE STRING "Flags used by the C compiler during RELEASE builds." FORCE)
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${b}" CACHE STRING "Flags used by the CXX compiler during RELEASE builds." FORCE)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
# disable silly warnings about using "deprecated" POSIX functions like fopen()
|
||||
add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
|
||||
add_definitions(-D_CRT_NONSTDC_NO_WARNINGS)
|
||||
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
# set __cplusplus according to selected C++ standard; use new preprocessor
|
||||
add_definitions(-Zc:__cplusplus -Zc:preprocessor)
|
||||
else()
|
||||
# protect against security threats caused by misguided compiler "optimizations"
|
||||
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
||||
add_definitions(-fno-delete-null-pointer-checks -fno-lifetime-dse)
|
||||
endif()
|
||||
add_definitions(-fno-strict-aliasing -fno-strict-overflow -funsigned-char)
|
||||
# disable overambitious auto-vectorization until this actually gains something
|
||||
add_definitions(-fno-tree-vectorize)
|
||||
endif()
|
||||
|
||||
# compile a target with -O2 in Debug build
|
||||
function(upx_compile_target_debug_with_O2 t)
|
||||
if(MSVC)
|
||||
# msvc uses some Debug compile options like -RTC1 that are incompatible with -O2
|
||||
else()
|
||||
target_compile_options(${t} PRIVATE $<$<CONFIG:Debug>:-O2>)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(upx_sanitize_target t)
|
||||
if(NOT UPX_CONFIG_DISABLE_SANITIZE AND NOT MSVC)
|
||||
if(CMAKE_C_PLATFORM_ID MATCHES "^MinGW" OR MINGW OR CYGWIN)
|
||||
# avoid link errors with current MinGW-w64 versions
|
||||
# see https://www.mingw-w64.org/contribute/#sanitizers-asan-tsan-usan
|
||||
else()
|
||||
# default sanitizer for Debug builds
|
||||
target_compile_options(${t} PRIVATE $<$<CONFIG:Debug>:-fsanitize=undefined -fsanitize-undefined-trap-on-error -fstack-protector-all>)
|
||||
# default sanitizer for Release builds
|
||||
target_compile_options(${t} PRIVATE $<$<CONFIG:Release>:-fstack-protector>)
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
set(t upx_vendor_ucl)
|
||||
target_include_directories(${t} PRIVATE vendor/ucl/include vendor/ucl)
|
||||
upx_compile_target_debug_with_O2(${t})
|
||||
upx_sanitize_target(${t})
|
||||
if(MSVC)
|
||||
target_compile_options(${t} PRIVATE -J -W4 ${warn_WX})
|
||||
else()
|
||||
target_compile_options(${t} PRIVATE ${warn_strict} ${warn_Werror})
|
||||
endif()
|
||||
|
||||
set(t upx_vendor_zlib)
|
||||
upx_compile_target_debug_with_O2(${t})
|
||||
upx_sanitize_target(${t})
|
||||
if(MSVC)
|
||||
target_compile_options(${t} PRIVATE -DHAVE_STDARG_H -DHAVE_VSNPRINTF -J -W3 ${warn_WX})
|
||||
else()
|
||||
target_compile_options(${t} PRIVATE -DHAVE_STDARG_H -DHAVE_UNISTD_H -DHAVE_VSNPRINTF)
|
||||
# clang-15: -Wno-strict-prototypes is needed to silence the new -Wdeprecated-non-prototype warning
|
||||
target_compile_options(${t} PRIVATE -Wall -Wextra -Wvla -Wno-strict-prototypes ${warn_Werror})
|
||||
endif()
|
||||
|
||||
if(NOT UPX_CONFIG_DISABLE_ZSTD)
|
||||
set(t upx_vendor_zstd)
|
||||
upx_compile_target_debug_with_O2(${t})
|
||||
upx_sanitize_target(${t})
|
||||
target_compile_options(${t} PRIVATE -DDYNAMIC_BMI2=0 -DZSTD_DISABLE_ASM)
|
||||
if(MSVC)
|
||||
target_compile_options(${t} PRIVATE -J -W4 ${warn_WX})
|
||||
else()
|
||||
target_compile_options(${t} PRIVATE ${warn_strict} ${warn_Werror})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(t upx)
|
||||
target_include_directories(${t} PRIVATE vendor vendor/boost-pfr/include)
|
||||
target_compile_definitions(${t} PRIVATE $<$<CONFIG:Debug>:DEBUG=1>)
|
||||
if(GITREV_SHORT)
|
||||
target_compile_definitions(${t} PRIVATE UPX_VERSION_GITREV="${GITREV_SHORT}${GITREV_PLUS}")
|
||||
if(GIT_DESCRIBE)
|
||||
target_compile_definitions(${t} PRIVATE UPX_VERSION_GIT_DESCRIBE="${GIT_DESCRIBE}")
|
||||
endif()
|
||||
endif()
|
||||
#upx_compile_target_debug_with_O2(${t})
|
||||
upx_sanitize_target(${t})
|
||||
if(MSVC)
|
||||
target_compile_options(${t} PRIVATE -EHsc -J -W4 ${warn_WX})
|
||||
else()
|
||||
target_compile_options(${t} PRIVATE ${warn_strict} ${warn_Werror})
|
||||
endif()
|
||||
if(NOT UPX_CONFIG_DISABLE_ZSTD)
|
||||
target_compile_definitions(${t} PRIVATE WITH_ZSTD=1)
|
||||
target_link_libraries(upx upx_vendor_zstd)
|
||||
endif()
|
||||
|
||||
#***********************************************************************
|
||||
# "ctest"
|
||||
# "make test"
|
||||
# "ninja test"
|
||||
#***********************************************************************
|
||||
|
||||
if(NOT UPX_CONFIG_CMAKE_DISABLE_TEST)
|
||||
|
||||
include(CTest)
|
||||
if(NOT CMAKE_CROSSCOMPILING)
|
||||
add_test(NAME upx-version COMMAND upx --version)
|
||||
add_test(NAME upx-help COMMAND upx --help)
|
||||
endif()
|
||||
if(NOT CMAKE_CROSSCOMPILING AND NOT UPX_CONFIG_DISABLE_SELF_PACK_TEST)
|
||||
# NOTE: these tests can only work if the host executable format is supported by UPX!
|
||||
function(upx_add_test)
|
||||
set(name ${ARGV0})
|
||||
list(REMOVE_AT ARGV 0)
|
||||
add_test(NAME ${name} COMMAND ${ARGV})
|
||||
set_tests_properties(${name} PROPERTIES RUN_SERIAL TRUE) # run these tests sequentially
|
||||
endfunction()
|
||||
set(exe ${CMAKE_EXECUTABLE_SUFFIX})
|
||||
set(upx_self_exe "$<TARGET_FILE:upx>")
|
||||
set(fo "--force-overwrite")
|
||||
upx_add_test(upx-self-pack upx -3 ${upx_self_exe} ${fo} -o upx-packed${exe})
|
||||
upx_add_test(upx-self-pack-n2b upx -3 --nrv2b ${upx_self_exe} ${fo} -o upx-packed-n2b${exe})
|
||||
upx_add_test(upx-self-pack-n2d upx -3 --nrv2d ${upx_self_exe} ${fo} -o upx-packed-n2d${exe})
|
||||
upx_add_test(upx-self-pack-n2e upx -3 --nrv2e ${upx_self_exe} ${fo} -o upx-packed-n2e${exe})
|
||||
upx_add_test(upx-self-pack-lzma upx -3 --lzma ${upx_self_exe} ${fo} -o upx-packed-lzma${exe})
|
||||
upx_add_test(upx-list upx -l upx-packed${exe} upx-packed-n2b${exe} upx-packed-n2d${exe} upx-packed-n2e${exe} upx-packed-lzma${exe})
|
||||
upx_add_test(upx-fileinfo upx --fileinfo upx-packed${exe} upx-packed-n2b${exe} upx-packed-n2d${exe} upx-packed-n2e${exe} upx-packed-lzma${exe})
|
||||
upx_add_test(upx-test upx -t upx-packed${exe} upx-packed-n2b${exe} upx-packed-n2d${exe} upx-packed-n2e${exe} upx-packed-lzma${exe})
|
||||
upx_add_test(upx-unpack upx -d upx-packed${exe} ${fo} -o upx-unpacked${exe})
|
||||
upx_add_test(upx-run-unpacked ./upx-unpacked${exe} --version-short)
|
||||
upx_add_test(upx-run-packed ./upx-packed${exe} --version-short)
|
||||
endif()
|
||||
|
||||
endif() # UPX_CONFIG_CMAKE_DISABLE_TEST
|
||||
|
||||
#***********************************************************************
|
||||
# "cmake --install ."
|
||||
# "make install"
|
||||
# "ninja install"
|
||||
#***********************************************************************
|
||||
|
||||
if(NOT UPX_CONFIG_CMAKE_DISABLE_INSTALL)
|
||||
|
||||
# installation prefix and directories
|
||||
if(NOT CMAKE_INSTALL_PREFIX)
|
||||
#message(FATAL_ERROR "ERROR: CMAKE_INSTALL_PREFIX is not defined.")
|
||||
message(WARNING "WARNING: CMAKE_INSTALL_PREFIX is not defined.")
|
||||
endif()
|
||||
if(CMAKE_INSTALL_PREFIX)
|
||||
include(GNUInstallDirs)
|
||||
endif()
|
||||
if(CMAKE_INSTALL_PREFIX AND DEFINED CMAKE_INSTALL_FULL_BINDIR)
|
||||
install(TARGETS upx DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}")
|
||||
install(FILES
|
||||
COPYING LICENSE NEWS README THANKS doc/upx-doc.html doc/upx-doc.txt
|
||||
DESTINATION "${CMAKE_INSTALL_FULL_DOCDIR}"
|
||||
)
|
||||
install(FILES doc/upx.1 DESTINATION "${CMAKE_INSTALL_FULL_MANDIR}/man1")
|
||||
endif()
|
||||
|
||||
endif() # UPX_CONFIG_CMAKE_DISABLE_INSTALL
|
||||
|
||||
#***********************************************************************
|
||||
# finally print some info about the build configuration
|
||||
#***********************************************************************
|
||||
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/maint/make/CMakeLists.maint.txt")
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/maint/make/CMakeLists.maint.txt")
|
||||
endif()
|
||||
|
||||
function(print_var)
|
||||
foreach(v ${ARGV})
|
||||
if(${v})
|
||||
message(STATUS "${v} = ${${v}}")
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
if(NOT UPX_CONFIG_CMAKE_DISABLE_PRINT_INFO)
|
||||
print_var(CMAKE_HOST_SYSTEM_NAME CMAKE_HOST_SYSTEM_VERSION)
|
||||
print_var(CMAKE_SYSTEM_NAME CMAKE_SYSTEM_VERSION CMAKE_CROSSCOMPILING)
|
||||
print_var(CMAKE_C_COMPILER_ID CMAKE_C_COMPILER_VERSION CMAKE_C_COMPILER_ARCHITECTURE_ID CMAKE_C_PLATFORM_ID CMAKE_C_COMPILER_ABI)
|
||||
print_var(CMAKE_CXX_COMPILER_ID CMAKE_CXX_COMPILER_VERSION CMAKE_CXX_COMPILER_ARCHITECTURE_ID CMAKE_CXX_PLATFORM_ID CMAKE_CXX_COMPILER_ABI)
|
||||
endif() # UPX_CONFIG_CMAKE_DISABLE_PRINT_INFO
|
||||
print_var(CMAKE_INSTALL_PREFIX CMAKE_CONFIGURATION_TYPES CMAKE_BUILD_TYPE)
|
||||
if (CMAKE_BUILD_TYPE AND NOT CMAKE_BUILD_TYPE MATCHES "^(Debug|Release)$")
|
||||
message(WARNING "WARNING: unsupported CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}; please use \"Debug\" or \"Release\"")
|
||||
endif()
|
||||
|
||||
if(NOT UPX_CONFIG_CMAKE_DISABLE_PLATFORM_CHECK)
|
||||
# extra sanity checks to detect incompatible C vs CXX settings
|
||||
if(NOT ",${CMAKE_C_PLATFORM_ID}," STREQUAL ",${CMAKE_CXX_PLATFORM_ID},")
|
||||
message(FATAL_ERROR "ERROR: CMAKE_C_PLATFORM_ID CMAKE_CXX_PLATFORM_ID mismatch")
|
||||
endif()
|
||||
if(NOT ",${CMAKE_C_COMPILER_ABI}," STREQUAL ",${CMAKE_CXX_COMPILER_ABI},")
|
||||
message(FATAL_ERROR "ERROR: CMAKE_C_COMPILER_ABI CMAKE_CXX_COMPILER_ABI mismatch")
|
||||
endif()
|
||||
endif() # UPX_CONFIG_CMAKE_DISABLE_PLATFORM_CHECK
|
||||
|
||||
# vim:set ft=cmake ts=4 sw=4 tw=0 et:
|
||||
@@ -1,48 +1,186 @@
|
||||
#
|
||||
# UPX toplevel Makefile - needs GNU make 3.81 or better
|
||||
# UPX top-level Makefile - needs GNU make and CMake >= 3.13
|
||||
#
|
||||
|
||||
MAKEFLAGS += -rR
|
||||
# INFO: this Makefile is just a convenience wrapper for calling CMake
|
||||
|
||||
# NOTE: if you only have an older CMake 3.x then you can invoke cmake manually like this:
|
||||
# mkdir -p build/release
|
||||
# cd build/release
|
||||
# cmake ../..
|
||||
# make -j (or use "cmake --build . --parallel")
|
||||
|
||||
CMAKE = cmake
|
||||
UPX_CMAKE_BUILD_FLAGS += --parallel
|
||||
ifneq ($(VERBOSE),)
|
||||
UPX_CMAKE_BUILD_FLAGS += --verbose
|
||||
endif
|
||||
# enable this if you prefer Ninja for the actual builds:
|
||||
#UPX_CMAKE_CONFIG_FLAGS += -G Ninja
|
||||
|
||||
#***********************************************************************
|
||||
# default
|
||||
#***********************************************************************
|
||||
|
||||
run_cmake_config = $(CMAKE) -S . -B $1 $(UPX_CMAKE_CONFIG_FLAGS) -DCMAKE_BUILD_TYPE=$2
|
||||
run_cmake_build = $(CMAKE) --build $1 $(UPX_CMAKE_BUILD_FLAGS) --config $2
|
||||
# avoid re-running run_cmake_config if CMakeCache.txt already exists
|
||||
run_config = $(if $(wildcard $1/CMakeCache.txt),,$(call run_cmake_config,$1,$2))
|
||||
run_build = $(call run_cmake_build,$1,$2)
|
||||
|
||||
.DEFAULT_GOAL = build/release
|
||||
|
||||
build/debug: PHONY
|
||||
$(call run_config,$@,Debug)
|
||||
$(call run_build,$@,Debug)
|
||||
|
||||
build/release: PHONY
|
||||
$(call run_config,$@,Release)
|
||||
$(call run_build,$@,Release)
|
||||
|
||||
# shortcuts
|
||||
all: build/debug build/release
|
||||
debug: build/debug
|
||||
release: build/release
|
||||
|
||||
.PHONY: PHONY
|
||||
.NOTPARALLEL: # because the actual builds use "cmake --parallel"
|
||||
.SUFFIXES:
|
||||
export SHELL = /bin/sh
|
||||
|
||||
ifneq ($(findstring $(firstword $(MAKE_VERSION)),3.77 3.78 3.78.1 3.79 3.79.1 3.80),)
|
||||
$(error GNU make 3.81 or better is required)
|
||||
# END of Makefile; extra stuff follows
|
||||
|
||||
#***********************************************************************
|
||||
# extra builds: some pre-defined build configurations
|
||||
#***********************************************************************
|
||||
|
||||
define run_config_and_build
|
||||
$(call run_config,$1,$2)
|
||||
$(call run_build,$1,$2)
|
||||
endef
|
||||
|
||||
# force building with clang/clang++
|
||||
build/extra/clang/debug: PHONY; $(call run_config_and_build,$@,Debug)
|
||||
build/extra/clang/release: PHONY; $(call run_config_and_build,$@,Release)
|
||||
build/extra/clang/%: export CC = clang
|
||||
build/extra/clang/%: export CXX = clang++
|
||||
|
||||
# force building with clang/clang++ -m32
|
||||
build/extra/clang-m32/debug: PHONY; $(call run_config_and_build,$@,Debug)
|
||||
build/extra/clang-m32/release: PHONY; $(call run_config_and_build,$@,Release)
|
||||
build/extra/clang-m32/%: export CC = clang -m32
|
||||
build/extra/clang-m32/%: export CXX = clang++ -m32
|
||||
|
||||
# force building with clang/clang++ -mx32
|
||||
build/extra/clang-mx32/debug: PHONY; $(call run_config_and_build,$@,Debug)
|
||||
build/extra/clang-mx32/release: PHONY; $(call run_config_and_build,$@,Release)
|
||||
build/extra/clang-mx32/%: export CC = clang -mx32
|
||||
build/extra/clang-mx32/%: export CXX = clang++ -mx32
|
||||
|
||||
# force building with clang/clang++ -m64
|
||||
build/extra/clang-m64/debug: PHONY; $(call run_config_and_build,$@,Debug)
|
||||
build/extra/clang-m64/release: PHONY; $(call run_config_and_build,$@,Release)
|
||||
build/extra/clang-m64/%: export CC = clang -m64
|
||||
build/extra/clang-m64/%: export CXX = clang++ -m64
|
||||
|
||||
# force building with gcc/g++
|
||||
build/extra/gcc/debug: PHONY; $(call run_config_and_build,$@,Debug)
|
||||
build/extra/gcc/release: PHONY; $(call run_config_and_build,$@,Release)
|
||||
build/extra/gcc/%: export CC = gcc
|
||||
build/extra/gcc/%: export CXX = g++
|
||||
|
||||
# force building with gcc/g++ -m32
|
||||
build/extra/gcc-m32/debug: PHONY; $(call run_config_and_build,$@,Debug)
|
||||
build/extra/gcc-m32/release: PHONY; $(call run_config_and_build,$@,Release)
|
||||
build/extra/gcc-m32/%: export CC = gcc -m32
|
||||
build/extra/gcc-m32/%: export CXX = g++ -m32
|
||||
|
||||
# force building with gcc/g++ -mx32
|
||||
build/extra/gcc-mx32/debug: PHONY; $(call run_config_and_build,$@,Debug)
|
||||
build/extra/gcc-mx32/release: PHONY; $(call run_config_and_build,$@,Release)
|
||||
build/extra/gcc-mx32/%: export CC = gcc -mx32
|
||||
build/extra/gcc-mx32/%: export CXX = g++ -mx32
|
||||
|
||||
# force building with gcc/g++ -m64
|
||||
build/extra/gcc-m64/debug: PHONY; $(call run_config_and_build,$@,Debug)
|
||||
build/extra/gcc-m64/release: PHONY; $(call run_config_and_build,$@,Release)
|
||||
build/extra/gcc-m64/%: export CC = gcc -m64
|
||||
build/extra/gcc-m64/%: export CXX = g++ -m64
|
||||
|
||||
# force building with clang Static Analyzer (scan-build)
|
||||
build/extra/scan-build/debug: PHONY; $(call run_config_and_build,$@,Debug)
|
||||
build/extra/scan-build/release: PHONY; $(call run_config_and_build,$@,Release)
|
||||
build/extra/scan-build/%: CMAKE := scan-build $(CMAKE)
|
||||
build/extra/scan-build/%: export CCC_CC ?= clang
|
||||
build/extra/scan-build/%: export CCC_CXX ?= clang++
|
||||
|
||||
# cross compiler: Linux glibc aarch64-linux-gnu
|
||||
build/extra/cross-linux-aarch64/debug: PHONY; $(call run_config_and_build,$@,Debug)
|
||||
build/extra/cross-linux-aarch64/release: PHONY; $(call run_config_and_build,$@,Release)
|
||||
build/extra/cross-linux-aarch64/%: export CC = aarch64-linux-gnu-gcc
|
||||
build/extra/cross-linux-aarch64/%: export CXX = aarch64-linux-gnu-g++
|
||||
|
||||
# cross compiler: Linux glibc arm-linux-gnueabihf
|
||||
build/extra/cross-linux-arm/debug: PHONY; $(call run_config_and_build,$@,Debug)
|
||||
build/extra/cross-linux-arm/release: PHONY; $(call run_config_and_build,$@,Release)
|
||||
build/extra/cross-linux-arm/%: export CC = arm-linux-gnueabihf-gcc
|
||||
build/extra/cross-linux-arm/%: export CXX = arm-linux-gnueabihf-g++ -Wno-psabi
|
||||
|
||||
# cross compiler: Windows x86 win32 MinGW
|
||||
build/extra/cross-windows-mingw32/debug: PHONY; $(call run_config_and_build,$@,Debug)
|
||||
build/extra/cross-windows-mingw32/release: PHONY; $(call run_config_and_build,$@,Release)
|
||||
build/extra/cross-windows-mingw32/%: export CC = i686-w64-mingw32-gcc
|
||||
build/extra/cross-windows-mingw32/%: export CXX = i686-w64-mingw32-g++
|
||||
|
||||
# cross compiler: Windows x64 win64 MinGW
|
||||
build/extra/cross-windows-mingw64/debug: PHONY; $(call run_config_and_build,$@,Debug)
|
||||
build/extra/cross-windows-mingw64/release: PHONY; $(call run_config_and_build,$@,Release)
|
||||
build/extra/cross-windows-mingw64/%: export CC = x86_64-w64-mingw32-gcc
|
||||
build/extra/cross-windows-mingw64/%: export CXX = x86_64-w64-mingw32-g++
|
||||
|
||||
# cross compiler: macOS arm64
|
||||
build/extra/cross-darwin-arm64/debug: PHONY; $(call run_config_and_build,$@,Debug)
|
||||
build/extra/cross-darwin-arm64/release: PHONY; $(call run_config_and_build,$@,Release)
|
||||
build/extra/cross-darwin-arm64/%: export CC = clang -target arm64-apple-darwin
|
||||
build/extra/cross-darwin-arm64/%: export CXX = clang++ -target arm64-apple-darwin
|
||||
|
||||
# cross compiler: macOS x86_64
|
||||
build/extra/cross-darwin-x86_64/debug: PHONY; $(call run_config_and_build,$@,Debug)
|
||||
build/extra/cross-darwin-x86_64/release: PHONY; $(call run_config_and_build,$@,Release)
|
||||
build/extra/cross-darwin-x86_64/%: export CC = clang -target x86_64-apple-darwin
|
||||
build/extra/cross-darwin-x86_64/%: export CXX = clang++ -target x86_64-apple-darwin
|
||||
|
||||
#***********************************************************************
|
||||
# advanced: generic extra target
|
||||
#***********************************************************************
|
||||
|
||||
# usage:
|
||||
# make UPX_XTARGET=my-target CC="my-cc -flags" CXX="my-cxx -flags"
|
||||
# make UPX_XTARGET=my-target CC="my-cc -flags" CXX="my-cxx -flags" xtarget/debug
|
||||
|
||||
ifneq ($(UPX_XTARGET),)
|
||||
ifneq ($(CC),)
|
||||
ifneq ($(CXX),)
|
||||
|
||||
UPX_XTARGET := $(UPX_XTARGET)
|
||||
build/xtarget/$(UPX_XTARGET)/debug: PHONY; $(call run_config_and_build,$@,Debug)
|
||||
build/xtarget/$(UPX_XTARGET)/release: PHONY; $(call run_config_and_build,$@,Release)
|
||||
build/xtarget/$(UPX_XTARGET)/%: export CC
|
||||
build/xtarget/$(UPX_XTARGET)/%: export CXX
|
||||
# shortcuts
|
||||
xtarget/debug: build/xtarget/$(UPX_XTARGET)/debug
|
||||
xtarget/release: build/xtarget/$(UPX_XTARGET)/release
|
||||
# set new default
|
||||
.DEFAULT_GOAL = xtarget/release
|
||||
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
srcdir = .
|
||||
top_srcdir = .
|
||||
include $(wildcard $(top_srcdir)/Makevars.global ./Makevars.local)
|
||||
#***********************************************************************
|
||||
# check git submodules
|
||||
#***********************************************************************
|
||||
|
||||
SUBMODULES = doctest lzma-sdk ucl valgrind zlib
|
||||
|
||||
# info: src/stub needs special build tools
|
||||
BUILD_STUB = 0
|
||||
ifneq ($(wildcard $(HOME)/local/bin/bin-upx/.),)
|
||||
BUILD_STUB = 1
|
||||
endif
|
||||
ifneq ($(wildcard $(HOME)/bin/bin-upx/.),)
|
||||
BUILD_STUB = 1
|
||||
endif
|
||||
|
||||
|
||||
default:
|
||||
@echo "UPX info: please choose a target for 'make'"
|
||||
|
||||
all mostlyclean clean distclean maintainer-clean:
|
||||
ifeq ($(BUILD_STUB),1)
|
||||
$(MAKE) -C src/stub $@
|
||||
endif
|
||||
$(MAKE) -C src $@
|
||||
$(MAKE) -C doc $@
|
||||
|
||||
|
||||
ifneq ($(wildcard .hg/.),)
|
||||
# automatically generate ChangeLog from local Mercurial repo
|
||||
ChangeLog:
|
||||
hg log --style=changelog > $@
|
||||
.PHONY: ChangeLog
|
||||
endif
|
||||
|
||||
|
||||
.PHONY: default all mostlyclean clean distclean maintainer-clean
|
||||
|
||||
dummy := $(foreach m,$(SUBMODULES),$(if $(wildcard vendor/$m/[CL]*),$m,\
|
||||
$(error ERROR: missing git submodule $m; run 'git submodule update --init')))
|
||||
|
||||
@@ -2,6 +2,112 @@
|
||||
User visible changes for UPX
|
||||
==================================================================
|
||||
|
||||
Changes in 4.0.2 (30 Jan 2023):
|
||||
* bug fixes - see https://github.com/upx/upx/milestone/9
|
||||
|
||||
Changes in 4.0.1 (16 Nov 2022):
|
||||
* bug fixes - see https://github.com/upx/upx/milestone/8
|
||||
|
||||
Changes in 4.0.0 (28 Oct 2022):
|
||||
* Switch to semantic versioning
|
||||
* SECURITY NOTES: emphasize the security context in the docs
|
||||
* Support easy building from source code with CMake
|
||||
* Support easy rebuilding the stubs from source with Podman/Docker
|
||||
* Add integrated doctest C++ testing framework
|
||||
* Add support for EFI files (PE x86; Kornel Pal)
|
||||
* win32/pe and win64/pe: set correct SizeOfHeaders in the PE header
|
||||
* bug fixes - see https://github.com/upx/upx/milestone/6
|
||||
* bug fixes - see https://github.com/upx/upx/milestone/7
|
||||
|
||||
Changes in 3.96 (23 Jan 2020):
|
||||
* bug fixes - see https://github.com/upx/upx/milestone/5
|
||||
|
||||
Changes in 3.95 (26 Aug 2018):
|
||||
* Flag --android-shlib to work around bad design in Android
|
||||
* Flag --force-pie when ET_DYN main program is not marked as DF_1_PIE
|
||||
* Better compatibility with varying layout of address space on Linux
|
||||
* Support for 4 PT_LOAD layout in ELF generated by binutils-2.31
|
||||
* bug fixes, particularly better diagnosis of malformed input
|
||||
* bug fixes - see https://github.com/upx/upx/milestone/4
|
||||
|
||||
Changes in 3.94 (12 May 2017):
|
||||
* Add support for arm64-linux (aka "aarch64").
|
||||
* Add support for --lzma compression on 64-bit PowerPC (Thierry Fauck).
|
||||
* For Mach, "upx -d" will unpack a prefix of the file (and warn).
|
||||
* Various improvements to the ELF formats.
|
||||
* bug fixes - see https://github.com/upx/upx/milestone/3
|
||||
|
||||
Changes in 3.93 (29 Jan 2017):
|
||||
* Fixed some win32/pe and win64/pe regressions introduced in 3.92
|
||||
* bug fixes - see https://github.com/upx/upx/milestone/2
|
||||
|
||||
Changes in 3.92 (11 Dec 2016):
|
||||
* INFO: UPX has moved to GitHub - the new home page is https://upx.github.io
|
||||
* IMPORTANT: all PE formats: internal changes: reunited the diverged source
|
||||
files - please report all regressions into the bug tracker and try UPX 3.91
|
||||
in case of problems.
|
||||
* Support Apple MacOS 10.12 "Sierra", including more-robust de-compression.
|
||||
* Explicitly diagnose Go-language bad PT_LOAD; recommend hemfix.c.
|
||||
https://sourceforge.net/p/upx/bugs/195/ https://github.com/pwaller/goupx
|
||||
* Fix CERT-FI Case 829767 UPX command line tools segfaults.
|
||||
Received by UPX Team on 2015-May-08; originally reported
|
||||
by Codenomicon to NCSC-FI on 2015-01-08.
|
||||
The vulnerabilities were discovered by Joonas Kuorilehto and
|
||||
Antti Häyrynen from Codenomicon.
|
||||
* bug fixes - see https://github.com/upx/upx/milestone/1
|
||||
|
||||
Changes in 3.91 (30 Sep 2013):
|
||||
* Added experimental support for Windows 64-bit PE files, based on
|
||||
work by Stefan Widmann. Please use for testing only!
|
||||
* bug fixes
|
||||
|
||||
==================================================================
|
||||
|
||||
Changes in 3.09 (18 Feb 2013):
|
||||
* New option --preserve-build-id for GNU ELF.
|
||||
* Allow for code signing and LC_UUID on Mac OS X executables.
|
||||
* Allow non-contiguous LC_SEGMENTs and 0==.vmsize for Mach-O.
|
||||
* Allow zero-filled final page in PackUnix::canUnpack().
|
||||
* bug fixes
|
||||
|
||||
Changes in 3.08 (12 Dec 2011):
|
||||
* Fix allocation in runtime stub for darwin.macho-entry (i386 and amd64).
|
||||
* Compress shared library on ELF i386 only [ld.so threatens even this case].
|
||||
* Attempt to support ELF on QNX 6.3.0 for armel (experimental).
|
||||
* Better diagnostic when ELF -fPIC is needed.
|
||||
* PT_NOTE improvements for *BSD.
|
||||
* Preserve more ELF .e_flags on ARM.
|
||||
* Minor code improvements for ELF stubs.
|
||||
* Defend against another flavor of corrupt PE header.
|
||||
* bug fixes
|
||||
|
||||
Changes in 3.07 (08 Sep 2010):
|
||||
* win32/pe: fixed relocation handling for files with *no* TLS callbacks
|
||||
[severe bug introduced in 3.06]
|
||||
|
||||
Changes in 3.06 (04 Sep 2010):
|
||||
* win32/pe: TLS callback support contributed by Stefan Widmann. Thanks!
|
||||
* bug fixes
|
||||
|
||||
Changes in 3.05 (27 Apr 2010):
|
||||
* i386-linux and amd64-linux support shared libraries (DT_INIT must
|
||||
exist, all info needed by runtime loader must be first in .text, etc.)
|
||||
* Linux /proc/self/exe now is preserved by default, by leaving behind
|
||||
one page. New compress-time option --unmap-all-pages is available.
|
||||
* Withdraw support for shared libraries on Darwin (Apple Mac OS X)
|
||||
because upx does not understand enough about .dylib.
|
||||
* bug fixes
|
||||
|
||||
Changes in 3.04 (27 Sep 2009):
|
||||
* new format Mach/AMD64 supports 64-bit programs on Apple Macintosh.
|
||||
* new formats Dylib/i386 and Dylib/ppc32 support shared libraries
|
||||
[such as browser plugins] on Darwin (Apple Macintosh). An existing
|
||||
-init function (LC_ROUTINES command) is required.
|
||||
* new format vmlinuz/armel for Debian NSLU2 (etc.) linux kernel
|
||||
* bvmlinuz boot protocol 2.08 for 386 Linux kernel
|
||||
* Extended ABI version 4 for armel-eabi ARM Linux ELF
|
||||
* bug fixes
|
||||
|
||||
Changes in 3.03 (27 Apr 2008):
|
||||
* implement cache flushing for PowerPC (esp. model 440)
|
||||
* fix cache flushing on MIPS (>3 MiB compressed, or with holes)
|
||||
@@ -32,7 +138,7 @@ Changes in 2.93 beta (08 Mar 2007):
|
||||
you have to explicitly use '--lzma' even for '--ultra-brute' here
|
||||
because runtime decompression is about 30 times slower than NRV -
|
||||
which is really noticeable on old machines.
|
||||
* dos/exe: fixed a rarely occuring bug in relocation handling
|
||||
* dos/exe: fixed a rarely occurring bug in relocation handling
|
||||
* win32/pe & arm/pe: better icon compression handling
|
||||
|
||||
Changes in 2.92 beta (23 Jan 2007):
|
||||
@@ -265,6 +371,8 @@ Changes in 0.99 (25 Feb 2000)
|
||||
* dos/com and dos/sys: fixed a bad decompressor problem
|
||||
* linux/386: the counter for the progress indicator was off by one
|
||||
|
||||
==================================================================
|
||||
|
||||
Changes in 0.94 (06 Dec 1999)
|
||||
* win32/pe: the stub now calls ExitProcess in case of import errors
|
||||
* under DOS and Windows, the environment variable UPX now accepts
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
ooooo ooo ooooooooo. ooooooo ooooo
|
||||
`888' `8' `888 `Y88. `8888 d8'
|
||||
888 8 888 .d88' Y888..8P
|
||||
888 8 888ooo88P' `8888'
|
||||
888 8 888 .8PY888.
|
||||
`88. .8' 888 d8' `888b
|
||||
`YbodP' o888o o888o o88888o
|
||||
|
||||
|
||||
The Ultimate Packer for eXecutables
|
||||
Copyright (c) 1996-2008 Markus Oberhumer, Laszlo Molnar & John Reiser
|
||||
http://upx.sourceforge.net
|
||||
|
||||
|
||||
Here are some possible projects from which you can choose if you'd like to
|
||||
contribute to UPX. Be sure to get in touch with us first to avoid
|
||||
duplicate efforts.
|
||||
|
||||
|
||||
User interface:
|
||||
---------------
|
||||
|
||||
- Write a nifty Win32 GUI (in C++), but try to keep the size of the
|
||||
final executable small. Compression should be in a separate
|
||||
thread that calls do_one_file() [see src/work.cpp].
|
||||
|
||||
- Draw a nice UPX icon.
|
||||
|
||||
|
||||
More formats:
|
||||
-------------
|
||||
|
||||
- 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.
|
||||
|
||||
- add support for self-extracting HTML pages using a Javascript stub
|
||||
(like the AlgART HTML Packer "AHP")
|
||||
|
||||
|
||||
Existing formats:
|
||||
-----------------
|
||||
|
||||
- djgpp2/coff: add support for DLX dynamic loading
|
||||
(see SEAL http://www.home.sk/public/seal/ )
|
||||
|
||||
- dos/com: add support for very long files - convert to exe if necessary
|
||||
|
||||
- dos/exe: implement filter support
|
||||
|
||||
- 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...)
|
||||
|
||||
- watcom/le: add support for per section compression, LX support, VXD
|
||||
|
||||
- win32/pe: display a nice dialog box in the stub in case
|
||||
of problems (like importing a DLL or function fails)
|
||||
- win32/pe: per section compression
|
||||
|
||||
|
||||
Compression ratio:
|
||||
------------------
|
||||
|
||||
- invent more effective filters
|
||||
|
||||
- I (Markus) will continue to work on better compression algorithms,
|
||||
so be sure to do better than me if you plan working on this ;-)
|
||||
|
||||
|
||||
Other:
|
||||
------
|
||||
|
||||
- anything else you think that could improve UPX...
|
||||
|
||||
|
||||
Thanks for your contribution.
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
ooooo ooo ooooooooo. ooooooo ooooo
|
||||
`888' `8' `888 `Y88. `8888 d8'
|
||||
888 8 888 .d88' Y888..8P
|
||||
888 8 888ooo88P' `8888'
|
||||
888 8 888 .8PY888.
|
||||
`88. .8' 888 d8' `888b
|
||||
`YbodP' o888o o888o o88888o
|
||||
ooooo ooo ooooooooo. ooooooo ooooo
|
||||
`888' `8' `888 `Y88. `8888 d8'
|
||||
888 8 888 .d88' Y888..8P
|
||||
888 8 888ooo88P' `8888'
|
||||
888 8 888 .8PY888.
|
||||
`88. .8' 888 d8' `888b
|
||||
`YbodP' o888o o888o o88888o
|
||||
|
||||
|
||||
The Ultimate Packer for eXecutables
|
||||
Copyright (c) 1996-2008 Markus Oberhumer, Laszlo Molnar & John Reiser
|
||||
http://upx.sourceforge.net
|
||||
Copyright (c) 1996-2023 Markus Oberhumer, Laszlo Molnar & John Reiser
|
||||
https://upx.github.io
|
||||
|
||||
|
||||
|
||||
@@ -18,10 +18,8 @@ WELCOME
|
||||
|
||||
Welcome to UPX !
|
||||
|
||||
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.
|
||||
UPX is a free, secure, portable, extendable, high-performance
|
||||
executable packer for several executable formats.
|
||||
|
||||
|
||||
INTRODUCTION
|
||||
@@ -37,106 +35,86 @@ 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
|
||||
Windows 95/98/ME/NT/2000/XP/CE programs and DLLs, DOS programs,
|
||||
and Linux executables and kernels.
|
||||
Windows programs and DLLs, macOS apps and Linux executables.
|
||||
|
||||
UPX is free software distributed under the term of the GNU General
|
||||
Public License. Full source code is available.
|
||||
|
||||
UPX may be distributed and used freely, even with commercial applications.
|
||||
See the UPX License Agreement for details.
|
||||
See the UPX License Agreements for details.
|
||||
|
||||
UPX is rated number one in the well known Archive Comparison Test. Visit
|
||||
http://compression.ca/ .
|
||||
|
||||
UPX aims to be Commercial Quality Freeware.
|
||||
SECURITY CONTEXT
|
||||
================
|
||||
|
||||
IMPORTANT NOTE: UPX inherits the security context of any files it handles.
|
||||
|
||||
This means that packing, unpacking, or even testing or listing a file requires
|
||||
the same security considerations as actually executing the file.
|
||||
|
||||
Use UPX on trusted files only!
|
||||
|
||||
|
||||
SHORT DOCUMENTATION
|
||||
===================
|
||||
|
||||
'upx program.exe' will compress a program or DLL. For best compression
|
||||
results try 'upx --brute program.exe'.
|
||||
results try 'upx --best program.exe' or 'upx --brute program.exe'.
|
||||
|
||||
Please see the file UPX.DOC for the full documentation. The files
|
||||
NEWS and BUGS also contain various tidbits of information.
|
||||
|
||||
|
||||
DISCLAIMER
|
||||
==========
|
||||
|
||||
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 8 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.
|
||||
|
||||
Please report all problems or suggestions to the authors. Thanks.
|
||||
|
||||
|
||||
THE FUTURE
|
||||
==========
|
||||
|
||||
- We'd really love to support handheld systems like the PalmPilot because
|
||||
compression makes a lot of sense here. And - because of the atari/tos
|
||||
format - we already have a working decompressor in 68000 assembly.
|
||||
Unfortunately we know next to nothing about the operating system
|
||||
architecture of such handhelds, so we need some information from
|
||||
an expert. Please contact us if you think you can help.
|
||||
- Stay up-to-date with ongoing OS and executable format changes
|
||||
|
||||
- The Linux approach could probably get ported to a lot of other Unix
|
||||
variants, at least for other i386 architectures it shouldn't be too
|
||||
much work. If someone sends me a fresh hard disk and an official
|
||||
FreeBSD/OpenBSD/NetBSD/Solaris/BeOS... CD I might take a look at it ;-)
|
||||
- RISC-V 64 for Linux
|
||||
|
||||
- ARM64 for Windows (help wanted)
|
||||
|
||||
- We will *NOT* add any sort of protection and/or encryption.
|
||||
This only gives people a false feeling of security because
|
||||
by definition all protectors/compressors can be broken.
|
||||
And don't trust any advertisement of authors of other executable
|
||||
compressors about this topic - just do a websearch on "unpackers"...
|
||||
all "protectors" can be broken by definition.
|
||||
|
||||
- Fix all remaining bugs - keep your reports coming ;-)
|
||||
|
||||
- See the file PROJECTS in the source code distribution if you want
|
||||
to contribute.
|
||||
- Fix all remaining bugs - please report any issues
|
||||
https://github.com/upx/upx/issues
|
||||
|
||||
|
||||
COPYRIGHT
|
||||
=========
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 2000-2008 John F. Reiser
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
Copyright (C) 2000-2023 John F. Reiser
|
||||
|
||||
This program may be used freely, and you are welcome to
|
||||
redistribute it under certain conditions.
|
||||
UPX is distributed with full source code under the terms of the
|
||||
GNU General Public License v2+; either under the pure GPLv2+ (see
|
||||
the file COPYING), or (at your option) under the GPLv+2 with special
|
||||
exceptions and restrictions granting the free usage for all binaries
|
||||
including commercial programs (see the file LICENSE).
|
||||
|
||||
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.
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
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.
|
||||
You should have received a copy of the UPX License Agreements along
|
||||
with this program; see the files COPYING and LICENSE. If not,
|
||||
visit the UPX home page.
|
||||
|
||||
|
||||
Share and enjoy,
|
||||
Markus & Laszlo
|
||||
Markus & Laszlo & John
|
||||
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
|
||||
John F. Reiser
|
||||
<jreiser@BitWagon.com>
|
||||
|
||||
|
||||
[ The term UPX is a shorthand for the Ultimate Packer for eXecutables
|
||||
and holds no connection with potential owners of registered trademarks
|
||||
or other rights. ]
|
||||
|
||||
[ Feel free to contact us if you have commercial compression requirements
|
||||
or interesting job offers. ]
|
||||
|
||||
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
ooooo ooo ooooooooo. ooooooo ooooo
|
||||
`888' `8' `888 `Y88. `8888 d8'
|
||||
888 8 888 .d88' Y888..8P
|
||||
888 8 888ooo88P' `8888'
|
||||
888 8 888 .8PY888.
|
||||
`88. .8' 888 d8' `888b
|
||||
`YbodP' o888o o888o o88888o
|
||||
|
||||
|
||||
The Ultimate Packer for eXecutables
|
||||
Copyright (c) 1996-2008 Markus Oberhumer, Laszlo Molnar & John Reiser
|
||||
http://upx.sourceforge.net
|
||||
|
||||
|
||||
MAJOR NEWS IN UPX 3
|
||||
===================
|
||||
|
||||
The main news since UPX 2 are:
|
||||
|
||||
* new format: added support for linux elf/arm
|
||||
|
||||
* better compression using the LZMA algorithm (option '--lzma')
|
||||
|
||||
+15
-58
@@ -27,21 +27,6 @@ Foreword
|
||||
Markus & Laszlo
|
||||
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Welcome to the UPX source code release!
|
||||
|
||||
UPX is not a toy for kids. Apart from basic knowledge about executables
|
||||
and data compression you will need to be firm in C++, assembler,
|
||||
Perl and Makefiles. Probably some other things as well.
|
||||
|
||||
If you can't manage to compile it then the sources are
|
||||
probably not for you. Don't email us for help.
|
||||
|
||||
The authors use Linux for development. You might want to as well.
|
||||
|
||||
|
||||
Short overview
|
||||
--------------
|
||||
|
||||
@@ -56,49 +41,34 @@ Short overview
|
||||
are #included by the individual executable format handlers.
|
||||
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
- first of all you need to build the UCL compression library
|
||||
http://www.oberhumer.com/opensource/ucl/
|
||||
|
||||
|
||||
Tools needed to build/modify the UPX sources
|
||||
--------------------------------------------
|
||||
|
||||
- A C++ compiler supporting inner classes, templates, exceptions
|
||||
and RTTI.
|
||||
- A C++ compiler that supports C++ 17: clang-5, gcc-8 or msvc-2019 16.11
|
||||
(older or other compilers may work but are unsupported, use at your own risk)
|
||||
|
||||
- GNU make 3.81 or better
|
||||
- GNU make
|
||||
|
||||
- CMake 3.13 or better; see https://cmake.org/
|
||||
|
||||
|
||||
To compile the packer sources
|
||||
-----------------------------
|
||||
|
||||
Set the environment variable UPX_UCLDIR to point to your
|
||||
UCL build directory, e.g.
|
||||
|
||||
set UPX_UCLDIR=c:\src\ucl-1.03 (DOS / Windows)
|
||||
export UPX_UCLDIR=$HOME/local/src/ucl-1.03 (Unix)
|
||||
|
||||
Set the environment variable UPX_LZMADIR to point to your
|
||||
to your unpacked lzma443.tar.bz2 source directory, e.g.
|
||||
|
||||
export UPX_LZMADIR=$HOME/local/src/lzma-4.43 (Unix)
|
||||
|
||||
Finally type
|
||||
|
||||
make
|
||||
- just run "make" in the top-level source directory
|
||||
|
||||
|
||||
If you want to modify the stub sources you'll also need
|
||||
-------------------------------------------------------
|
||||
|
||||
- Perl & Python
|
||||
- Podman/Docker: see misc/rebuild-stubs-with-podman - this
|
||||
is the preferred way of rebuilding the stubs
|
||||
|
||||
- A number of cross-assemblers and cross-compilers - precompiled
|
||||
binaries for i386-linux hosts are available from
|
||||
http://sourceforge.net/project/showfiles.php?group_id=2331
|
||||
- otherwise you will need:
|
||||
- a Linux host system with Perl, Python2 and some older compat-libs
|
||||
- upx-stubtools - a number of cross-assemblers and cross-compilers.
|
||||
Precompiled binaries for amd64-linux hosts are available from
|
||||
https://github.com/upx/upx-stubtools/releases
|
||||
|
||||
|
||||
Misc. notes
|
||||
@@ -114,9 +84,9 @@ Misc. notes
|
||||
- Use gcc extensions and other compiler specific stuff only through
|
||||
macros.
|
||||
|
||||
***
|
||||
|
||||
Some conventions:
|
||||
-----------------
|
||||
|
||||
- follow our coding style
|
||||
- indent level = 4
|
||||
@@ -125,17 +95,4 @@ Some conventions:
|
||||
- Use throwSomeException() functions instead of throw SomeException():
|
||||
this makes the code shorter if used often.
|
||||
|
||||
***
|
||||
|
||||
Patches/Contributions
|
||||
|
||||
- Please send us bug fixes/contributions only using
|
||||
|
||||
diff -u oldfile newfile
|
||||
|
||||
or
|
||||
|
||||
diff -uNr olddirectory newdirectory
|
||||
|
||||
|
||||
# vi:ts=4:et
|
||||
# vim:set ts=4 sw=4 et:
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
ooooo ooo ooooooooo. ooooooo ooooo
|
||||
`888' `8' `888 `Y88. `8888 d8'
|
||||
888 8 888 .d88' Y888..8P
|
||||
888 8 888ooo88P' `8888'
|
||||
888 8 888 .8PY888.
|
||||
`88. .8' 888 d8' `888b
|
||||
`YbodP' o888o o888o o88888o
|
||||
ooooo ooo ooooooooo. ooooooo ooooo
|
||||
`888' `8' `888 `Y88. `8888 d8'
|
||||
888 8 888 .d88' Y888..8P
|
||||
888 8 888ooo88P' `8888'
|
||||
888 8 888 .8PY888.
|
||||
`88. .8' 888 d8' `888b
|
||||
`YbodP' o888o o888o o88888o
|
||||
|
||||
|
||||
The Ultimate Packer for eXecutables
|
||||
Copyright (c) 1996-2008 Markus Oberhumer, Laszlo Molnar & John Reiser
|
||||
http://upx.sourceforge.net
|
||||
Copyright (c) 1996-2023 Markus Oberhumer, Laszlo Molnar & John Reiser
|
||||
https://upx.github.io
|
||||
|
||||
|
||||
.___.. .
|
||||
@@ -53,7 +53,8 @@ Ralph Roth <RalphRoth@gmx.net>
|
||||
for reporting several bugs
|
||||
Salvador Eduardo Tropea
|
||||
for beta testing
|
||||
The WINE project (http://www.winehq.com/)
|
||||
Stefan Widmann
|
||||
for the win32/pe TLS callback support
|
||||
The WINE project (https://www.winehq.com/)
|
||||
for lots of useful information found in their PE loader sources
|
||||
Natascha
|
||||
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
UPX TODO list. Last updated 2006-12-08.
|
||||
|
||||
|
||||
IMPORTANT PROBLEMS THAT SHOULD BE FIXED SOON:
|
||||
|
||||
- [None]
|
||||
|
||||
|
||||
OTHER:
|
||||
|
||||
- docs: convert docs from upx.pod to use AsciiDoc
|
||||
|
||||
- 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_*).
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
|
||||
IMPROVED COMPRESSION RATIO
|
||||
==========================
|
||||
|
||||
- experiment with new filters
|
||||
|
||||
- implement filters for dos/exe
|
||||
|
||||
- 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
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
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
|
||||
================
|
||||
|
||||
- handle files without relocations
|
||||
|
||||
- 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
|
||||
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
-std=gnu++17
|
||||
-Ivendor
|
||||
-fno-strict-aliasing
|
||||
-fno-strict-overflow
|
||||
-funsigned-char
|
||||
+10
-11
@@ -1,15 +1,15 @@
|
||||
ooooo ooo ooooooooo. ooooooo ooooo
|
||||
`888' `8' `888 `Y88. `8888 d8'
|
||||
888 8 888 .d88' Y888..8P
|
||||
888 8 888ooo88P' `8888'
|
||||
888 8 888 .8PY888.
|
||||
`88. .8' 888 d8' `888b
|
||||
`YbodP' o888o o888o o88888o
|
||||
ooooo ooo ooooooooo. ooooooo ooooo
|
||||
`888' `8' `888 `Y88. `8888 d8'
|
||||
888 8 888 .d88' Y888..8P
|
||||
888 8 888ooo88P' `8888'
|
||||
888 8 888 .8PY888.
|
||||
`88. .8' 888 d8' `888b
|
||||
`YbodP' o888o o888o o88888o
|
||||
|
||||
|
||||
The Ultimate Packer for eXecutables
|
||||
Copyright (c) 1996-2008 Markus Oberhumer, Laszlo Molnar & John Reiser
|
||||
http://upx.sourceforge.net
|
||||
Copyright (c) 1996-2023 Markus Oberhumer, Laszlo Molnar & John Reiser
|
||||
https://upx.github.io
|
||||
|
||||
|
||||
Limitations and other things which are not (yet) supported:
|
||||
@@ -44,8 +44,7 @@ test file.
|
||||
|
||||
win32/pe
|
||||
--------
|
||||
* writeable shared sections (`--force' *may* work)
|
||||
* writable shared sections (`--force' *may* work)
|
||||
* certificates in the image
|
||||
* compressing files which contain a big BSS requires lots of memory
|
||||
during compression
|
||||
|
||||
+34
-48
@@ -1,29 +1,8 @@
|
||||
#
|
||||
# UPX doc Makefile - needs GNU make 3.80 or better
|
||||
# UPX doc Makefile - needs GNU make, pod2html, pod2man and pod2text
|
||||
#
|
||||
|
||||
MAKEFLAGS += -rR
|
||||
.SUFFIXES:
|
||||
SHELL = /bin/sh
|
||||
|
||||
# internal make variables
|
||||
comma := ,
|
||||
empty :=
|
||||
space := $(empty) $(empty)
|
||||
tab := $(empty) $(empty)
|
||||
|
||||
# update $PATH for our special stub build tools
|
||||
ifneq ($(wildcard $(HOME)/local/bin/bin-upx/.),)
|
||||
export PATH := $(HOME)/local/bin/bin-upx:$(PATH)
|
||||
endif
|
||||
ifneq ($(wildcard $(HOME)/bin/bin-upx/.),)
|
||||
export PATH := $(HOME)/bin/bin-upx:$(PATH)
|
||||
endif
|
||||
|
||||
|
||||
# /***********************************************************************
|
||||
# //
|
||||
# ************************************************************************/
|
||||
BUILT_SOURCES = upx.1 upx-doc.html upx-doc.txt
|
||||
|
||||
top_srcdir ?= ..
|
||||
|
||||
@@ -31,55 +10,62 @@ PACKAGE = upx
|
||||
VERSION_DATE := $(shell sed -n 's/^.*UPX_VERSION_DATE_ISO .*"\(.*\)".*/\1/p' $(top_srcdir)/src/version.h)
|
||||
VERSION := $(shell sed -n 's/^.*UPX_VERSION_STRING .*"\(.*\)".*/\1/p' $(top_srcdir)/src/version.h)
|
||||
|
||||
# internal make variables
|
||||
comma := ,
|
||||
empty :=
|
||||
space := $(empty) $(empty)
|
||||
tab := $(empty) $(empty)
|
||||
|
||||
RTRIM := sed -e 's/[ $(tab)]*$$//'
|
||||
DETAB2 := sed -e 's/$(tab)/ /g'
|
||||
|
||||
BUILT_SOURCES = upx.1 upx.doc upx.html upx.man upx.ps upx.tex
|
||||
BUILT_SOURCES = upx.1 upx.doc upx.html
|
||||
#***********************************************************************
|
||||
# targets
|
||||
#***********************************************************************
|
||||
|
||||
.DEFAULT_GOAL = all
|
||||
|
||||
###
|
||||
### targets
|
||||
###
|
||||
all: $(BUILT_SOURCES) PHONY
|
||||
|
||||
all: $(BUILT_SOURCES)
|
||||
mostlyclean clean distclean maintainer-clean: PHONY
|
||||
rm -f $(BUILT_SOURCES) ./pod2htm*
|
||||
|
||||
mostlyclean clean distclean maintainer-clean:
|
||||
rm -f $(BUILT_SOURCES) pod2htm*
|
||||
#***********************************************************************
|
||||
# rules
|
||||
#***********************************************************************
|
||||
|
||||
.PHONY: all mostlyclean clean distclean maintainer-clean
|
||||
|
||||
|
||||
###
|
||||
### rules
|
||||
###
|
||||
|
||||
.SUFFIXES: .1 .doc .html .man .pod .ps .tex
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .1 .html .man .pod .ps .tex .txt
|
||||
|
||||
%.1 : %.pod
|
||||
pod2man --center=" " --release="$(PACKAGE) $(VERSION)" --date="$(VERSION_DATE)" $< | $(RTRIM) > $@
|
||||
test -s $@
|
||||
|
||||
%.doc : %.pod
|
||||
pod2text < $< | $(RTRIM) > $@
|
||||
|
||||
%.html : %.pod
|
||||
%-doc.html : %.pod
|
||||
pod2html --noindex $< | $(RTRIM) | $(DETAB2) > $@
|
||||
@rm -f pod2htm*
|
||||
@rm -f ./pod2htm*
|
||||
test -s $@
|
||||
|
||||
%.man : %.1
|
||||
nroff -man $< | $(RTRIM) > $@
|
||||
test -s $@
|
||||
|
||||
%.ps : %.1
|
||||
groff -man $< | $(RTRIM) > $@
|
||||
test -s $@
|
||||
|
||||
%.tex : %.pod
|
||||
pod2latex $<
|
||||
test -s $@
|
||||
|
||||
%-doc.txt : %.pod
|
||||
pod2text < $< | $(RTRIM) > $@
|
||||
test -s $@
|
||||
|
||||
###
|
||||
### dependencies
|
||||
###
|
||||
#***********************************************************************
|
||||
# dependencies
|
||||
#***********************************************************************
|
||||
|
||||
$(BUILT_SOURCES): $(top_srcdir)/src/version.h $(MAKEFILE_LIST)
|
||||
.DELETE_ON_ERROR: $(BUILT_SOURCES)
|
||||
|
||||
.PHONY: PHONY
|
||||
|
||||
+37
-11
@@ -1,5 +1,5 @@
|
||||
Decompressing ELF Directly to Memory on Linux/x86
|
||||
Copyright (C) 2000-2008 John F. Reiser jreiser@BitWagon.com
|
||||
Copyright (C) 2000-2023 John F. Reiser jreiser@BitWagon.com
|
||||
|
||||
References:
|
||||
<elf.h> definitions for the ELF file format
|
||||
@@ -64,16 +64,42 @@ assuming that its automatic stack variables are initialized to zero),
|
||||
and remove (all but 4 bytes of) the decompression program (and
|
||||
compressed executable) from the address space.
|
||||
|
||||
Because the UPX runtime stub removes all traces of the compressed file
|
||||
from the address space, then the Linux kernel erases the symlink
|
||||
/proc/self/exe. Linux stores the pathname argument that was specified
|
||||
to execve() immediately after the '\0' which terminates the character
|
||||
string of the last environment variable [as of execve()]. This is true
|
||||
for at least all Linux 2.6, 2.4, and 2.2 kernels. The pathname is not
|
||||
"bound" to the file as strongly as /proc/self/exe (the file may be changed
|
||||
without affecting the pathname), but the pathname does provide some
|
||||
information. The pathname may be relative to the working directory,
|
||||
so look before any chdir().
|
||||
As of upx-3.05, by default on Linux, upon decompression then one page
|
||||
of the compressed executable remains mapped into the address space
|
||||
of the process. If all of the pages of the compressed executable are
|
||||
unmapped, then the Linux kernel erases the symlink /proc/self/exe,
|
||||
and this can cause trouble for the runtime shared library loader
|
||||
expanding $ORIGIN in -rpath, or for application code that relies on
|
||||
/proc/self/exe. Use the compress-time command-line option
|
||||
--unmap-all-pages to achieve that effect at run time. Upx-3.04
|
||||
and previous versions did this by default with no option. However,
|
||||
too much other software erroneously assumes that /proc/self/exe
|
||||
always exists.
|
||||
|
||||
On arm*-linux-elf there is no good address at which to retain one
|
||||
page of the compressed executable. Pages below the usual .p_vaddr
|
||||
0x8000 (32KiB) are rejected by the kernel. Using a page above the
|
||||
original uncompressed brk(0) would require placing the entire initial
|
||||
compressed program above uncompressed brk(0), which would significantly
|
||||
increase the running brk(0); but too many programs break if brk(0)
|
||||
moves. Thus on arm*-linux-elf the compressed executable begins
|
||||
with 0x8000==.p_vaddr, all pages mapped by execve() that are also
|
||||
occupied by decompressed bytes are removed before overwriting, and
|
||||
/proc/self/exe becomes a "(deleted)" symlink. It might be possible
|
||||
to preserve /proc/self/exe if the original uncompressed executable
|
||||
were created with 0x9000==.p_vaddr (one page higher than the usual
|
||||
0x8000) so that the compressed page mapped at 0x8000 would linger.
|
||||
[This has not been tested.]
|
||||
|
||||
Linux stores the pathname argument that was specified to execve()
|
||||
immediately after the '\0' which terminates the character string of the
|
||||
last environment variable [as of execve()]. This is true for at least
|
||||
all Linux 2.6, 2.4, and 2.2 kernels. Linux kernel 2.6.29 and later
|
||||
records a pointer to that character string in Elf32_auxv[AT_EXECFN].
|
||||
The pathname is not "bound" to the file as strongly as /proc/self/exe
|
||||
(the file may be changed without affecting the pathname), but the
|
||||
pathname does provide some information. The pathname may be relative
|
||||
to the working directory, so look before any chdir().
|
||||
|
||||
The Elf formats for Linux add an environment variable named " " [three
|
||||
spaces] which saves the results of readlink("/proc/self/exe",,) before
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ code 127, and a record will be added to the history file
|
||||
|
||||
In "targeted enforcing" mode, SELinux pays close attention mostly to
|
||||
designated processes that run with elevated privileges: web server,
|
||||
print server, login server, etc. Ordinary user excutables receive
|
||||
print server, login server, etc. Ordinary user executables receive
|
||||
much less scrutiny. However, one of the eventual goals of SELinux is to
|
||||
eradicate runtime generation of instructions because of the possibility
|
||||
for exploitation by malware (virus, trojan, key logger, privilege
|
||||
|
||||
@@ -0,0 +1,807 @@
|
||||
<?xml version="1.0" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>upx - compress or expand executable files</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<link rev="made" href="mailto:root@localhost" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
<h1 id="NAME">NAME</h1>
|
||||
|
||||
<p>upx - compress or expand executable files</p>
|
||||
|
||||
<h1 id="SYNOPSIS">SYNOPSIS</h1>
|
||||
|
||||
<p><b>upx</b> <span style="white-space: nowrap;">[ <i>command</i> ]</span> <span style="white-space: nowrap;">[ <i>options</i> ]</span> <i>filename</i>...</p>
|
||||
|
||||
<h1 id="ABSTRACT">ABSTRACT</h1>
|
||||
|
||||
<pre><code> The Ultimate Packer for eXecutables
|
||||
Copyright (c) 1996-2023 Markus Oberhumer, Laszlo Molnar & John Reiser
|
||||
https://upx.github.io</code></pre>
|
||||
|
||||
<p><b>UPX</b> is a portable, extendable, high-performance executable packer for several different executable formats. It achieves an excellent compression ratio and offers <i>*very*</i> fast decompression. Your executables suffer no memory overhead or other drawbacks for most of the formats supported, because of in-place decompression.</p>
|
||||
|
||||
<h1 id="DISCLAIMER">DISCLAIMER</h1>
|
||||
|
||||
<p><b>UPX</b> comes with ABSOLUTELY NO WARRANTY; for details see the file COPYING.</p>
|
||||
|
||||
<p>Please report all problems or suggestions to the authors. Thanks.</p>
|
||||
|
||||
<h1 id="SECURITY-CONTEXT">SECURITY CONTEXT</h1>
|
||||
|
||||
<p>IMPORTANT NOTE: <b>UPX</b> inherits the security context of any files it handles.</p>
|
||||
|
||||
<p>This means that packing, unpacking, or even testing or listing a file requires the same security considerations as actually executing the file.</p>
|
||||
|
||||
<p>Use <b>UPX</b> on trusted files only!</p>
|
||||
|
||||
<h1 id="DESCRIPTION">DESCRIPTION</h1>
|
||||
|
||||
<p><b>UPX</b> is a versatile executable packer with the following features:</p>
|
||||
|
||||
<pre><code>- secure: as UPX is documented Open Source since many years any relevant
|
||||
Security/Antivirus software is able to peek inside UPX compressed
|
||||
apps to verify them
|
||||
|
||||
- excellent compression ratio: typically compresses better than Zip,
|
||||
use UPX to decrease the size of your distribution !
|
||||
|
||||
- very fast decompression: more than 500 MB/sec on any reasonably modern
|
||||
machine
|
||||
|
||||
- no memory overhead for your compressed executables for most of the
|
||||
supported formats because of in-place decompression
|
||||
|
||||
- safe: you can list, test and unpack your executables.
|
||||
Also, a checksum of both the compressed and uncompressed file is
|
||||
maintained internally.
|
||||
|
||||
- universal: UPX can pack a number of executable formats, including
|
||||
Windows programs and DLLs, macOS apps and Linux executables
|
||||
|
||||
- portable: UPX is written in portable endian-neutral C++
|
||||
|
||||
- extendable: because of the class layout it's very easy to support
|
||||
new executable formats or add new compression algorithms
|
||||
|
||||
- free: UPX is distributed with full source code under the GNU General
|
||||
Public License v2+, with special exceptions granting the free usage
|
||||
for commercial programs</code></pre>
|
||||
|
||||
<p>You probably understand now why we call <b>UPX</b> the "<i>ultimate</i>" executable packer.</p>
|
||||
|
||||
<h1 id="COMMANDS">COMMANDS</h1>
|
||||
|
||||
<h2 id="Compress">Compress</h2>
|
||||
|
||||
<p>This is the default operation, eg. <b>upx yourfile.exe</b> will compress the file specified on the command line.</p>
|
||||
|
||||
<h2 id="Decompress">Decompress</h2>
|
||||
|
||||
<p>All <b>UPX</b> supported file formats can be unpacked using the <b>-d</b> switch, eg. <b>upx -d yourfile.exe</b> will uncompress the file you've just compressed.</p>
|
||||
|
||||
<h2 id="Test">Test</h2>
|
||||
|
||||
<p>The <b>-t</b> command tests the integrity of the compressed and uncompressed data, eg. <b>upx -t yourfile.exe</b> check whether your file can be safely decompressed. Note, that this command doesn't check the whole file, only the part that will be uncompressed during program execution. This means that you should not use this command instead of a virus checker.</p>
|
||||
|
||||
<h2 id="List">List</h2>
|
||||
|
||||
<p>The <b>-l</b> command prints out some information about the compressed files specified on the command line as parameters, eg <b>upx -l yourfile.exe</b> shows the compressed / uncompressed size and the compression ratio of <i>yourfile.exe</i>.</p>
|
||||
|
||||
<h1 id="OPTIONS">OPTIONS</h1>
|
||||
|
||||
<p><b>-q</b>: be quiet, suppress warnings</p>
|
||||
|
||||
<p><b>-q -q</b> (or <b>-qq</b>): be very quiet, suppress errors</p>
|
||||
|
||||
<p><b>-q -q -q</b> (or <b>-qqq</b>): produce no output at all</p>
|
||||
|
||||
<p><b>--help</b>: prints the help</p>
|
||||
|
||||
<p><b>--version</b>: print the version of <b>UPX</b></p>
|
||||
|
||||
<p><b>--exact</b>: when compressing, require to be able to get a byte-identical file after decompression with option <b>-d</b>. [NOTE: this is work in progress and is not supported for all formats yet. If you do care, as a workaround you can compress and then decompress your program a first time - any further compress-decompress steps should then yield byte-identical results as compared to the first decompressed version.]</p>
|
||||
|
||||
<p><b>-k</b>: keep backup files</p>
|
||||
|
||||
<p><b>-o file</b>: write output to file</p>
|
||||
|
||||
<p>[ ...more docs need to be written... - type `<b>upx --help</b>' for now ]</p>
|
||||
|
||||
<h1 id="COMPRESSION-LEVELS-TUNING">COMPRESSION LEVELS & TUNING</h1>
|
||||
|
||||
<p><b>UPX</b> offers ten different compression levels from <b>-1</b> to <b>-9</b>, and <b>--best</b>. The default compression level is <b>-8</b> for files smaller than 512 KiB, and <b>-7</b> otherwise.</p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li><p>Compression levels 1, 2 and 3 are pretty fast.</p>
|
||||
|
||||
</li>
|
||||
<li><p>Compression levels 4, 5 and 6 achieve a good time/ratio performance.</p>
|
||||
|
||||
</li>
|
||||
<li><p>Compression levels 7, 8 and 9 favor compression ratio over speed.</p>
|
||||
|
||||
</li>
|
||||
<li><p>Compression level <b>--best</b> may take a long time.</p>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Note that compression level <b>--best</b> can be somewhat slow for large files, but you definitely should use it when releasing a final version of your program.</p>
|
||||
|
||||
<p>Quick info for achieving the best compression ratio:</p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li><p>Try <b>upx --brute --no-lzma myfile.exe</b> or even <b>upx --ultra-brute --no-lzma myfile.exe</b>.</p>
|
||||
|
||||
</li>
|
||||
<li><p>The option <b>--lzma</b> enables LZMA compression, which compresses better but is *significantly slower* at decompression. You probably do not want to use it for large files.</p>
|
||||
|
||||
<p>(Note that <b>--lzma</b> is automatically enabled by <b>--all-methods</b> and <b>--brute</b>, use <b>--no-lzma</b> to override.)</p>
|
||||
|
||||
</li>
|
||||
<li><p>Try if <b>--overlay=strip</b> works.</p>
|
||||
|
||||
</li>
|
||||
<li><p>For win32/pe programs there's <b>--strip-relocs=0</b>. See notes below.</p>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h1 id="OVERLAY-HANDLING-OPTIONS">OVERLAY HANDLING OPTIONS</h1>
|
||||
|
||||
<p>Info: An "overlay" means auxiliary data attached after the logical end of an executable, and it often contains application specific data (this is a common practice to avoid an extra data file, though it would be better to use resource sections).</p>
|
||||
|
||||
<p><b>UPX</b> handles overlays like many other executable packers do: it simply copies the overlay after the compressed image. This works with some files, but doesn't work with others, depending on how an application actually accesses this overlayed data.</p>
|
||||
|
||||
<pre><code>--overlay=copy Copy any extra data attached to the file. [DEFAULT]
|
||||
|
||||
--overlay=strip Strip any overlay from the program instead of
|
||||
copying it. Be warned, this may make the compressed
|
||||
program crash or otherwise unusable.
|
||||
|
||||
--overlay=skip Refuse to compress any program which has an overlay.</code></pre>
|
||||
|
||||
<h1 id="ENVIRONMENT-VARIABLE">ENVIRONMENT VARIABLE</h1>
|
||||
|
||||
<p>The environment variable <b>UPX</b> can hold a set of default options for <b>UPX</b>. These options are interpreted first and can be overwritten by explicit command line parameters. For example:</p>
|
||||
|
||||
<pre><code>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"</code></pre>
|
||||
|
||||
<p>Under DOS/Windows you must use '#' instead of '=' when setting the environment variable because of a COMMAND.COM limitation.</p>
|
||||
|
||||
<p>Not all of the options are valid in the environment variable - <b>UPX</b> will tell you.</p>
|
||||
|
||||
<p>You can explicitly use the <b>--no-env</b> option to ignore the environment variable.</p>
|
||||
|
||||
<h1 id="NOTES-FOR-THE-SUPPORTED-EXECUTABLE-FORMATS">NOTES FOR THE SUPPORTED EXECUTABLE FORMATS</h1>
|
||||
|
||||
<h2 id="NOTES-FOR-ATARI-TOS">NOTES FOR ATARI/TOS</h2>
|
||||
|
||||
<p>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 :-). See https://freemint.github.io for more info.</p>
|
||||
|
||||
<p>Packed programs will be byte-identical to the original after uncompression. All debug information will be stripped, though.</p>
|
||||
|
||||
<p>Extra options available for this executable format:</p>
|
||||
|
||||
<pre><code>--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.</code></pre>
|
||||
|
||||
<h2 id="NOTES-FOR-BVMLINUZ-I386">NOTES FOR BVMLINUZ/I386</h2>
|
||||
|
||||
<p>Same as vmlinuz/i386.</p>
|
||||
|
||||
<h2 id="NOTES-FOR-DOS-COM">NOTES FOR DOS/COM</h2>
|
||||
|
||||
<p>Obviously <b>UPX</b> won't work with executables that want to read data from themselves (like some commandline utilities that ship with Win95/98/ME).</p>
|
||||
|
||||
<p>Compressed programs only work on a 286+.</p>
|
||||
|
||||
<p>Packed programs will be byte-identical to the original after uncompression.</p>
|
||||
|
||||
<p>Maximum uncompressed size: ~65100 bytes.</p>
|
||||
|
||||
<p>Extra options available for this executable format:</p>
|
||||
|
||||
<pre><code>--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.</code></pre>
|
||||
|
||||
<h2 id="NOTES-FOR-DOS-EXE">NOTES FOR DOS/EXE</h2>
|
||||
|
||||
<p>dos/exe stands for all "normal" 16-bit DOS executables.</p>
|
||||
|
||||
<p>Obviously <b>UPX</b> won't work with executables that want to read data from themselves (like some command line utilities that ship with Win95/98/ME).</p>
|
||||
|
||||
<p>Compressed programs only work on a 286+.</p>
|
||||
|
||||
<p>Extra options available for this executable format:</p>
|
||||
|
||||
<pre><code>--8086 Create an executable that works on any 8086 CPU.
|
||||
|
||||
--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.</code></pre>
|
||||
|
||||
<h2 id="NOTES-FOR-DOS-SYS">NOTES FOR DOS/SYS</h2>
|
||||
|
||||
<p>Compressed programs only work on a 286+.</p>
|
||||
|
||||
<p>Packed programs will be byte-identical to the original after uncompression.</p>
|
||||
|
||||
<p>Maximum uncompressed size: ~65350 bytes.</p>
|
||||
|
||||
<p>Extra options available for this executable format:</p>
|
||||
|
||||
<pre><code>--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.</code></pre>
|
||||
|
||||
<h2 id="NOTES-FOR-DJGPP2-COFF">NOTES FOR DJGPP2/COFF</h2>
|
||||
|
||||
<p>First of all, it is recommended to use <b>UPX</b> *instead* of <b>strip</b>. strip has the very bad habit of replacing your stub with its own (outdated) version. Additionally <b>UPX</b> corrects a bug/feature in strip v2.8.x: it will fix the 4 KiB alignment of the stub.</p>
|
||||
|
||||
<p><b>UPX</b> includes the full functionality of stubify. This means it will automatically stubify your COFF files. Use the option <b>--coff</b> to disable this functionality (see below).</p>
|
||||
|
||||
<p><b>UPX</b> automatically handles Allegro packfiles.</p>
|
||||
|
||||
<p>The DLM format (a rather exotic shared library extension) is not supported.</p>
|
||||
|
||||
<p>Packed programs will be byte-identical to the original after uncompression. All debug information and trailing garbage will be stripped, though.</p>
|
||||
|
||||
<p>Extra options available for this executable format:</p>
|
||||
|
||||
<pre><code>--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.</code></pre>
|
||||
|
||||
<h2 id="NOTES-FOR-LINUX-general">NOTES FOR LINUX [general]</h2>
|
||||
|
||||
<p>Introduction</p>
|
||||
|
||||
<pre><code>Linux/386 support in UPX consists of 3 different executable formats,
|
||||
one optimized for ELF executables ("linux/elf386"), one optimized
|
||||
for shell scripts ("linux/sh386"), and one generic format
|
||||
("linux/386").
|
||||
|
||||
We will start with a general discussion first, but please
|
||||
also read the relevant docs for each of the individual formats.
|
||||
|
||||
Also, there is special support for bootable kernels - see the
|
||||
description of the vmlinuz/386 format.</code></pre>
|
||||
|
||||
<p>General user's overview</p>
|
||||
|
||||
<pre><code>Running a compressed executable program trades less space on a
|
||||
``permanent'' storage medium (such as a hard disk, floppy disk,
|
||||
CD-ROM, flash memory, EPROM, etc.) for more space in one or more
|
||||
``temporary'' storage media (such as RAM, swap space, /tmp, etc.).
|
||||
Running a compressed executable also requires some additional CPU
|
||||
cycles to generate the compressed executable in the first place,
|
||||
and to decompress it at each invocation.
|
||||
|
||||
How much space is traded? It depends on the executable, but many
|
||||
programs save 30% to 50% of permanent disk space. How much CPU
|
||||
overhead is there? Again, it depends on the executable, but
|
||||
decompression speed generally is at least many megabytes per second,
|
||||
and frequently is limited by the speed of the underlying disk
|
||||
or network I/O.
|
||||
|
||||
Depending on the statistics of usage and access, and the relative
|
||||
speeds of CPU, RAM, swap space, /tmp, and file system storage, then
|
||||
invoking and running a compressed executable can be faster than
|
||||
directly running the corresponding uncompressed program.
|
||||
The operating system might perform fewer expensive I/O operations
|
||||
to invoke the compressed program. Paging to or from swap space
|
||||
or /tmp might be faster than paging from the general file system.
|
||||
``Medium-sized'' programs which access about 1/3 to 1/2 of their
|
||||
stored program bytes can do particularly well with compression.
|
||||
Small programs tend not to benefit as much because the absolute
|
||||
savings is less. Big programs tend not to benefit proportionally
|
||||
because each invocation may use only a small fraction of the program,
|
||||
yet UPX decompresses the entire program before invoking it.
|
||||
But in environments where disk or flash memory storage is limited,
|
||||
then compression may win anyway.
|
||||
|
||||
Currently, executables compressed by UPX do not share RAM at runtime
|
||||
in the way that executables mapped from a file system do. As a
|
||||
result, if the same program is run simultaneously by more than one
|
||||
process, then using the compressed version will require more RAM and/or
|
||||
swap space. So, shell programs (bash, csh, etc.) and ``make''
|
||||
might not be good candidates for compression.
|
||||
|
||||
UPX recognizes three executable formats for Linux: Linux/elf386,
|
||||
Linux/sh386, and Linux/386. Linux/386 is the most generic format;
|
||||
it accommodates any file that can be executed. At runtime, the UPX
|
||||
decompression stub re-creates in /tmp a copy of the original file,
|
||||
and then the copy is (re-)executed with the same arguments.
|
||||
ELF binary executables prefer the Linux/elf386 format by default,
|
||||
because UPX decompresses them directly into RAM, uses only one
|
||||
exec, does not use space in /tmp, and does not use /proc.
|
||||
Shell scripts where the underlying shell accepts a ``-c'' argument
|
||||
can use the Linux/sh386 format. 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''.</code></pre>
|
||||
|
||||
<p>General benefits:</p>
|
||||
|
||||
<pre><code>- UPX can compress all executables, be it AOUT, ELF, libc4, libc5,
|
||||
libc6, Shell/Perl/Python/... scripts, standalone Java .class
|
||||
binaries, or whatever...
|
||||
All scripts and programs will work just as before.
|
||||
|
||||
- Compressed programs are completely self-contained. No need for
|
||||
any external program.
|
||||
|
||||
- UPX keeps your original program untouched. This means that
|
||||
after decompression you will have a byte-identical version,
|
||||
and you can use UPX as a file compressor just like gzip.
|
||||
[ Note that UPX maintains a checksum of the file internally,
|
||||
so it is indeed a reliable alternative. ]
|
||||
|
||||
- As the stub only uses syscalls and isn't linked against libc it
|
||||
should run under any Linux configuration that can run ELF
|
||||
binaries.
|
||||
|
||||
- For the same reason compressed executables should run under
|
||||
FreeBSD and other systems which can run Linux binaries.
|
||||
[ Please send feedback on this topic ]</code></pre>
|
||||
|
||||
<p>General drawbacks:</p>
|
||||
|
||||
<pre><code>- It is not advisable to compress programs which usually have many
|
||||
instances running (like `sh' or `make') because the common segments of
|
||||
compressed programs won't be shared any longer between different
|
||||
processes.
|
||||
|
||||
- `ldd' and `size' won't show anything useful because all they
|
||||
see is the statically linked stub. Since version 0.82 the section
|
||||
headers are stripped from the UPX stub and `size' doesn't even
|
||||
recognize the file format. The file patches/patch-elfcode.h has a
|
||||
patch to fix this bug in `size' and other programs which use GNU BFD.</code></pre>
|
||||
|
||||
<p>General notes:</p>
|
||||
|
||||
<pre><code>- As UPX leaves your original program untouched it is advantageous
|
||||
to strip it before compression.
|
||||
|
||||
- If you compress a script you will lose platform independence -
|
||||
this could be a problem if you are using NFS mounted disks.
|
||||
|
||||
- Compression of suid, guid and sticky-bit programs is rejected
|
||||
because of possible security implications.
|
||||
|
||||
- For the same reason there is no sense in making any compressed
|
||||
program suid.
|
||||
|
||||
- Obviously UPX won't work with executables that want to read data
|
||||
from themselves. E.g., this might be a problem for Perl scripts
|
||||
which access their __DATA__ lines.
|
||||
|
||||
- In case of internal errors the stub will abort with exitcode 127.
|
||||
Typical reasons for this to happen are that the program has somehow
|
||||
been modified after compression.
|
||||
Running `strace -o strace.log compressed_file' will tell you more.</code></pre>
|
||||
|
||||
<h2 id="NOTES-FOR-LINUX-ELF386">NOTES FOR LINUX/ELF386</h2>
|
||||
|
||||
<p>Please read the general Linux description first.</p>
|
||||
|
||||
<p>The linux/elf386 format decompresses directly into RAM, uses only one exec, does not use space in /tmp, and does not use /proc.</p>
|
||||
|
||||
<p>Linux/elf386 is automatically selected for Linux ELF executables.</p>
|
||||
|
||||
<p>Packed programs will be byte-identical to the original after uncompression.</p>
|
||||
|
||||
<p>How it works:</p>
|
||||
|
||||
<pre><code>For ELF executables, UPX decompresses directly to memory, simulating
|
||||
the mapping that the operating system kernel uses during exec(),
|
||||
including the PT_INTERP program interpreter (if any).
|
||||
The brk() is set by a special PT_LOAD segment in the compressed
|
||||
executable itself. UPX then wipes the stack clean except for
|
||||
arguments, environment variables, and Elf_auxv entries (this is
|
||||
required by bugs in the startup code of /lib/ld-linux.so as of
|
||||
May 2000), and transfers control to the program interpreter or
|
||||
the e_entry address of the original executable.
|
||||
|
||||
The UPX stub is about 1700 bytes long, partly written in assembler
|
||||
and only uses kernel syscalls. It is not linked against any libc.</code></pre>
|
||||
|
||||
<p>Specific drawbacks:</p>
|
||||
|
||||
<pre><code>- For linux/elf386 and linux/sh386 formats, you will be relying on
|
||||
RAM and swap space to hold all of the decompressed program during
|
||||
the lifetime of the process. If you already use most of your swap
|
||||
space, then you may run out. A system that is "out of memory"
|
||||
can become fragile. Many programs do not react gracefully when
|
||||
malloc() returns 0. With newer Linux kernels, the kernel
|
||||
may decide to kill some processes to regain memory, and you
|
||||
may not like the kernel's choice of which to kill. Running
|
||||
/usr/bin/top is one way to check on the usage of swap space.</code></pre>
|
||||
|
||||
<p>Extra options available for this executable format:</p>
|
||||
|
||||
<pre><code>(none)</code></pre>
|
||||
|
||||
<h2 id="NOTES-FOR-LINUX-SH386">NOTES FOR LINUX/SH386</h2>
|
||||
|
||||
<p>Please read the general Linux description first.</p>
|
||||
|
||||
<p>Shell scripts where the underling shell accepts a ``-c'' argument can use the Linux/sh386 format. <b>UPX</b> 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.</p>
|
||||
|
||||
<p>Linux/sh386 is automatically selected for shell scripts that use a known shell.</p>
|
||||
|
||||
<p>Packed programs will be byte-identical to the original after uncompression.</p>
|
||||
|
||||
<p>How it works:</p>
|
||||
|
||||
<pre><code>For shell script executables (files beginning with "#!/" or "#! /")
|
||||
where the shell is known to accept "-c <command>", UPX decompresses
|
||||
the file into low memory, then maps the shell (and its PT_INTERP),
|
||||
and passes control to the shell with the entire decompressed file
|
||||
as the argument after "-c". Known shells are sh, ash, bash, bsh, csh,
|
||||
ksh, tcsh, pdksh. Restriction: UPX cannot use this method
|
||||
for shell scripts which use the one optional string argument after
|
||||
the shell name in the script (example: "#! /bin/sh option3\n".)
|
||||
|
||||
The UPX stub is about 1700 bytes long, partly written in assembler
|
||||
and only uses kernel syscalls. It is not linked against any libc.</code></pre>
|
||||
|
||||
<p>Specific drawbacks:</p>
|
||||
|
||||
<pre><code>- For linux/elf386 and linux/sh386 formats, you will be relying on
|
||||
RAM and swap space to hold all of the decompressed program during
|
||||
the lifetime of the process. If you already use most of your swap
|
||||
space, then you may run out. A system that is "out of memory"
|
||||
can become fragile. Many programs do not react gracefully when
|
||||
malloc() returns 0. With newer Linux kernels, the kernel
|
||||
may decide to kill some processes to regain memory, and you
|
||||
may not like the kernel's choice of which to kill. Running
|
||||
/usr/bin/top is one way to check on the usage of swap space.</code></pre>
|
||||
|
||||
<p>Extra options available for this executable format:</p>
|
||||
|
||||
<pre><code>(none)</code></pre>
|
||||
|
||||
<h2 id="NOTES-FOR-LINUX-386">NOTES FOR LINUX/386</h2>
|
||||
|
||||
<p>Please read the general Linux description first.</p>
|
||||
|
||||
<p>The generic linux/386 format decompresses to /tmp and needs /proc file system support. It starts the decompressed program via the execve() syscall.</p>
|
||||
|
||||
<p>Linux/386 is only selected if the specialized linux/elf386 and linux/sh386 won't recognize a file.</p>
|
||||
|
||||
<p>Packed programs will be byte-identical to the original after uncompression.</p>
|
||||
|
||||
<p>How it works:</p>
|
||||
|
||||
<pre><code>For files which are not ELF and not a script for a known "-c" shell,
|
||||
UPX uses kernel execve(), which first requires decompressing to a
|
||||
temporary file in the file system. Interestingly -
|
||||
because of the good memory management of the Linux kernel - this
|
||||
often does not introduce a noticeable delay, and in fact there
|
||||
will be no disk access at all if you have enough free memory as
|
||||
the entire process takes places within the file system buffers.
|
||||
|
||||
A compressed executable consists of the UPX stub and an overlay
|
||||
which contains the original program in a compressed form.
|
||||
|
||||
The UPX stub is a statically linked ELF executable and does
|
||||
the following at program startup:
|
||||
|
||||
1) decompress the overlay to a temporary location in /tmp
|
||||
2) open the temporary file for reading
|
||||
3) try to delete the temporary file and start (execve)
|
||||
the uncompressed program in /tmp using /proc/<pid>/fd/X as
|
||||
attained by step 2)
|
||||
4) if that fails, fork off a subprocess to clean up and
|
||||
start the program in /tmp in the meantime
|
||||
|
||||
The UPX stub is about 1700 bytes long, partly written in assembler
|
||||
and only uses kernel syscalls. It is not linked against any libc.</code></pre>
|
||||
|
||||
<p>Specific drawbacks:</p>
|
||||
|
||||
<pre><code>- You need additional free disk space for the uncompressed program
|
||||
in your /tmp directory. This program is deleted immediately after
|
||||
decompression, but you still need it for the full execution time
|
||||
of the program.
|
||||
|
||||
- You must have /proc file system support as the stub wants to open
|
||||
/proc/<pid>/exe and needs /proc/<pid>/fd/X. This also means that you
|
||||
cannot compress programs that are used during the boot sequence
|
||||
before /proc is mounted.
|
||||
|
||||
- Utilities like `top' will display numerical values in the process
|
||||
name field. This is because Linux computes the process name from
|
||||
the first argument of the last execve syscall (which is typically
|
||||
something like /proc/<pid>/fd/3).
|
||||
|
||||
- Because of temporary decompression to disk the decompression speed
|
||||
is not as fast as with the other executable formats. Still, I can see
|
||||
no noticeable delay when starting programs like my ~3 MiB emacs (which
|
||||
is less than 1 MiB when compressed :-).</code></pre>
|
||||
|
||||
<p>Extra options available for this executable format:</p>
|
||||
|
||||
<pre><code>--force-execve Force the use of the generic linux/386 "execve"
|
||||
format, i.e. do not try the linux/elf386 and
|
||||
linux/sh386 formats.</code></pre>
|
||||
|
||||
<h2 id="NOTES-FOR-PS1-EXE">NOTES FOR PS1/EXE</h2>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>Packed programs will be byte-identical to the original after uncompression, until further notice.</p>
|
||||
|
||||
<p>Maximum uncompressed size: ~1.89 / ~7.60 MiB.</p>
|
||||
|
||||
<p>Notes:</p>
|
||||
|
||||
<pre><code>- UPX creates as default a suitable executable for CD-Mastering
|
||||
and console transfer. For a CD-Master main executable you could also try
|
||||
the special option "--boot-only" as described below.
|
||||
It has been reported that upx packed executables are fully compatible with
|
||||
the Sony PlayStation 2 (PS2, PStwo) and Sony PlayStation Portable (PSP) in
|
||||
Sony PlayStation (PSone) emulation mode.
|
||||
|
||||
- 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 relocate the loading address
|
||||
for the packed file, but this isn't a real problem if it is a single or
|
||||
the main executable.</code></pre>
|
||||
|
||||
<p>Extra options available for this executable format:</p>
|
||||
|
||||
<pre><code>--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.
|
||||
|
||||
--8-bit Uses 8 bit size compression [default: 32 bit]
|
||||
|
||||
--8mib-ram PSone has 8 MiB ram available [default: 2 MiB]
|
||||
|
||||
--boot-only This format is for main exes and CD-Mastering only !
|
||||
It may slightly improve the compression ratio,
|
||||
decompression routines are faster than default ones.
|
||||
But it cannot be used for console transfer !
|
||||
|
||||
--no-align This option disables CD mode 2 data sector format
|
||||
alignment. May slightly improves the compression ratio,
|
||||
but the compressed executable will not boot from a CD.
|
||||
Use it for console transfer only !</code></pre>
|
||||
|
||||
<h2 id="NOTES-FOR-RTM32-PE-and-ARM-PE">NOTES FOR RTM32/PE and ARM/PE</h2>
|
||||
|
||||
<p>Same as win32/pe.</p>
|
||||
|
||||
<h2 id="NOTES-FOR-TMT-ADAM">NOTES FOR TMT/ADAM</h2>
|
||||
|
||||
<p>This format is used by the TMT Pascal compiler - see http://www.tmt.com/ .</p>
|
||||
|
||||
<p>Extra options available for this executable format:</p>
|
||||
|
||||
<pre><code>--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.</code></pre>
|
||||
|
||||
<h2 id="NOTES-FOR-VMLINUZ-386">NOTES FOR VMLINUZ/386</h2>
|
||||
|
||||
<p>The vmlinuz/386 and bvmlinuz/386 formats take a gzip-compressed bootable Linux kernel image ("vmlinuz", "zImage", "bzImage"), gzip-decompress it and re-compress it with the <b>UPX</b> compression method.</p>
|
||||
|
||||
<p>vmlinuz/386 is completely unrelated to the other Linux executable formats, and it does not share any of their drawbacks.</p>
|
||||
|
||||
<p>Notes:</p>
|
||||
|
||||
<pre><code>- Be sure that "vmlinuz/386" or "bvmlinuz/386" is displayed
|
||||
during compression - otherwise a wrong executable format
|
||||
may have been used, and the kernel won't boot.</code></pre>
|
||||
|
||||
<p>Benefits:</p>
|
||||
|
||||
<pre><code>- Better compression (but note that the kernel was already compressed,
|
||||
so the improvement is not as large as with other formats).
|
||||
Still, the bytes saved may be essential for special needs like
|
||||
boot disks.
|
||||
|
||||
For example, this is what I get for my 2.2.16 kernel:
|
||||
1589708 vmlinux
|
||||
641073 bzImage [original]
|
||||
560755 bzImage.upx [compressed by "upx -9"]
|
||||
|
||||
- Much faster decompression at kernel boot time (but kernel
|
||||
decompression speed is not really an issue these days).</code></pre>
|
||||
|
||||
<p>Drawbacks:</p>
|
||||
|
||||
<pre><code>(none)</code></pre>
|
||||
|
||||
<p>Extra options available for this executable format:</p>
|
||||
|
||||
<pre><code>--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.</code></pre>
|
||||
|
||||
<h2 id="NOTES-FOR-WATCOM-LE">NOTES FOR WATCOM/LE</h2>
|
||||
|
||||
<p><b>UPX</b> 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).</p>
|
||||
|
||||
<p>DLLs and the LX format are not supported.</p>
|
||||
|
||||
<p>Extra options available for this executable format:</p>
|
||||
|
||||
<pre><code>--le Produce an unbound LE output instead of
|
||||
keeping the current stub.</code></pre>
|
||||
|
||||
<h2 id="NOTES-FOR-WIN32-PE">NOTES FOR WIN32/PE</h2>
|
||||
|
||||
<p>The PE support in <b>UPX</b> is quite stable now, but probably there are still some incompatibilities with some files.</p>
|
||||
|
||||
<p>Because of the way <b>UPX</b> (and other packers for this format) works, you can see increased memory usage of your compressed files because the whole program is loaded into memory at startup. If you start several instances of huge compressed programs you're wasting memory because the common segments of the program won't get shared across the instances. On the other hand if you're compressing only smaller programs, or running only one instance of larger programs, then this penalty is smaller, but it's still there.</p>
|
||||
|
||||
<p>If you're running executables from network, then compressed programs will load faster, and require less bandwidth during execution.</p>
|
||||
|
||||
<p>DLLs are supported. But UPX compressed DLLs can not share common data and code when they got used by multiple applications. So compressing msvcrt.dll is a waste of memory, but compressing the dll plugins of a particular application may be a better idea.</p>
|
||||
|
||||
<p>Screensavers are supported, with the restriction that the filename must end with ".scr" (as screensavers are handled slightly different than normal exe files).</p>
|
||||
|
||||
<p>UPX compressed PE files have some minor memory overhead (usually in the 10 - 30 KiB range) which can be seen by specifying the "-i" command line switch during compression.</p>
|
||||
|
||||
<p>Extra options available for this executable format:</p>
|
||||
|
||||
<pre><code>--compress-exports=0 Don't compress the export section.
|
||||
Use this if you plan to run the compressed
|
||||
program under Wine.
|
||||
--compress-exports=1 Compress the export section. [DEFAULT]
|
||||
Compression of the export section can improve the
|
||||
compression ratio quite a bit but may not work
|
||||
with all programs (like winword.exe).
|
||||
UPX never compresses the export section of a DLL
|
||||
regardless of this option.
|
||||
|
||||
--compress-icons=0 Don't compress any icons.
|
||||
--compress-icons=1 Compress all but the first icon.
|
||||
--compress-icons=2 Compress all icons which are not in the
|
||||
first icon directory. [DEFAULT]
|
||||
--compress-icons=3 Compress all icons.
|
||||
|
||||
--compress-resources=0 Don't compress any resources at all.
|
||||
|
||||
--keep-resource=list Don't compress resources specified by the list.
|
||||
The members of the list are separated by commas.
|
||||
A list member has the following format: I<type[/name]>.
|
||||
I<Type> is the type of the resource. Standard types
|
||||
must be specified as decimal numbers, user types can be
|
||||
specified by decimal IDs or strings. I<Name> is the
|
||||
identifier of the resource. It can be a decimal number
|
||||
or a string. For example:
|
||||
|
||||
--keep-resource=2/MYBITMAP,5,6/12345
|
||||
|
||||
UPX won't compress the named bitmap resource "MYBITMAP",
|
||||
it leaves every dialog (5) resource uncompressed, and
|
||||
it won't touch the string table resource with identifier
|
||||
12345.
|
||||
|
||||
--force Force compression even when there is an
|
||||
unexpected value in a header field.
|
||||
Use with care.
|
||||
|
||||
--strip-relocs=0 Don't strip relocation records.
|
||||
--strip-relocs=1 Strip relocation records. [DEFAULT]
|
||||
This option only works on executables with base
|
||||
address greater or equal to 0x400000. Usually the
|
||||
compressed files becomes smaller, but some files
|
||||
may become larger. Note that the resulting file will
|
||||
not work under Windows 3.x (Win32s).
|
||||
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.</code></pre>
|
||||
|
||||
<h1 id="DIAGNOSTICS">DIAGNOSTICS</h1>
|
||||
|
||||
<p>Exit status is normally 0; if an error occurs, exit status is 1. If a warning occurs, exit status is 2.</p>
|
||||
|
||||
<p><b>UPX</b>'s diagnostics are intended to be self-explanatory.</p>
|
||||
|
||||
<h1 id="BUGS">BUGS</h1>
|
||||
|
||||
<p>Please report all bugs immediately to the authors.</p>
|
||||
|
||||
<h1 id="AUTHORS">AUTHORS</h1>
|
||||
|
||||
<pre><code>Markus F.X.J. Oberhumer <markus@oberhumer.com>
|
||||
http://www.oberhumer.com
|
||||
|
||||
Laszlo Molnar <ezerotven+github@gmail.com>
|
||||
|
||||
John F. Reiser <jreiser@BitWagon.com>
|
||||
|
||||
Jens Medoch <jssg@users.sourceforge.net></code></pre>
|
||||
|
||||
<h1 id="COPYRIGHT">COPYRIGHT</h1>
|
||||
|
||||
<p>Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer</p>
|
||||
|
||||
<p>Copyright (C) 1996-2023 Laszlo Molnar</p>
|
||||
|
||||
<p>Copyright (C) 2000-2023 John F. Reiser</p>
|
||||
|
||||
<p>Copyright (C) 2002-2023 Jens Medoch</p>
|
||||
|
||||
<p><b>UPX</b> is distributed with full source code under the terms of the GNU General Public License v2+; either under the pure GPLv2+ (see the file COPYING), or (at your option) under the GPLv+2 with special exceptions and restrictions granting the free usage for all binaries including commercial programs (see the file LICENSE).</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>You should have received a copy of the UPX License Agreements along with this program; see the files COPYING and LICENSE. If not, visit the UPX home page.</p>
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
|
||||
+842
@@ -0,0 +1,842 @@
|
||||
NAME
|
||||
upx - compress or expand executable files
|
||||
|
||||
SYNOPSIS
|
||||
upx [ *command* ] [ *options* ] *filename*...
|
||||
|
||||
ABSTRACT
|
||||
The Ultimate Packer for eXecutables
|
||||
Copyright (c) 1996-2023 Markus Oberhumer, Laszlo Molnar & John Reiser
|
||||
https://upx.github.io
|
||||
|
||||
UPX is a portable, extendable, high-performance executable packer for
|
||||
several different executable formats. It achieves an excellent
|
||||
compression ratio and offers **very** fast decompression. Your
|
||||
executables suffer no memory overhead or other drawbacks for most of the
|
||||
formats supported, because of in-place decompression.
|
||||
|
||||
DISCLAIMER
|
||||
UPX comes with ABSOLUTELY NO WARRANTY; for details see the file COPYING.
|
||||
|
||||
Please report all problems or suggestions to the authors. Thanks.
|
||||
|
||||
SECURITY CONTEXT
|
||||
IMPORTANT NOTE: UPX inherits the security context of any files it
|
||||
handles.
|
||||
|
||||
This means that packing, unpacking, or even testing or listing a file
|
||||
requires the same security considerations as actually executing the
|
||||
file.
|
||||
|
||||
Use UPX on trusted files only!
|
||||
|
||||
DESCRIPTION
|
||||
UPX is a versatile executable packer with the following features:
|
||||
|
||||
- secure: as UPX is documented Open Source since many years any relevant
|
||||
Security/Antivirus software is able to peek inside UPX compressed
|
||||
apps to verify them
|
||||
|
||||
- excellent compression ratio: typically compresses better than Zip,
|
||||
use UPX to decrease the size of your distribution !
|
||||
|
||||
- very fast decompression: more than 500 MB/sec on any reasonably modern
|
||||
machine
|
||||
|
||||
- no memory overhead for your compressed executables for most of the
|
||||
supported formats because of in-place decompression
|
||||
|
||||
- safe: you can list, test and unpack your executables.
|
||||
Also, a checksum of both the compressed and uncompressed file is
|
||||
maintained internally.
|
||||
|
||||
- universal: UPX can pack a number of executable formats, including
|
||||
Windows programs and DLLs, macOS apps and Linux executables
|
||||
|
||||
- portable: UPX is written in portable endian-neutral C++
|
||||
|
||||
- extendable: because of the class layout it's very easy to support
|
||||
new executable formats or add new compression algorithms
|
||||
|
||||
- free: UPX is distributed with full source code under the GNU General
|
||||
Public License v2+, with special exceptions granting the free usage
|
||||
for commercial programs
|
||||
|
||||
You probably understand now why we call UPX the "*ultimate*" executable
|
||||
packer.
|
||||
|
||||
COMMANDS
|
||||
Compress
|
||||
This is the default operation, eg. upx yourfile.exe will compress the
|
||||
file specified on the command line.
|
||||
|
||||
Decompress
|
||||
All UPX supported file formats can be unpacked using the -d switch, eg.
|
||||
upx -d yourfile.exe will uncompress the file you've just compressed.
|
||||
|
||||
Test
|
||||
The -t command tests the integrity of the compressed and uncompressed
|
||||
data, eg. upx -t yourfile.exe check whether your file can be safely
|
||||
decompressed. Note, that this command doesn't check the whole file, only
|
||||
the part that will be uncompressed during program execution. This means
|
||||
that you should not use this command instead of a virus checker.
|
||||
|
||||
List
|
||||
The -l command prints out some information about the compressed files
|
||||
specified on the command line as parameters, eg upx -l yourfile.exe
|
||||
shows the compressed / uncompressed size and the compression ratio of
|
||||
*yourfile.exe*.
|
||||
|
||||
OPTIONS
|
||||
-q: be quiet, suppress warnings
|
||||
|
||||
-q -q (or -qq): be very quiet, suppress errors
|
||||
|
||||
-q -q -q (or -qqq): produce no output at all
|
||||
|
||||
--help: prints the help
|
||||
|
||||
--version: print the version of UPX
|
||||
|
||||
--exact: when compressing, require to be able to get a byte-identical
|
||||
file after decompression with option -d. [NOTE: this is work in progress
|
||||
and is not supported for all formats yet. If you do care, as a
|
||||
workaround you can compress and then decompress your program a first
|
||||
time - any further compress-decompress steps should then yield
|
||||
byte-identical results as compared to the first decompressed version.]
|
||||
|
||||
-k: keep backup files
|
||||
|
||||
-o file: write output to file
|
||||
|
||||
[ ...more docs need to be written... - type `upx --help' for now ]
|
||||
|
||||
COMPRESSION LEVELS & TUNING
|
||||
UPX offers ten different compression levels from -1 to -9, and --best.
|
||||
The default compression level is -8 for files smaller than 512 KiB, and
|
||||
-7 otherwise.
|
||||
|
||||
* Compression levels 1, 2 and 3 are pretty fast.
|
||||
|
||||
* Compression levels 4, 5 and 6 achieve a good time/ratio performance.
|
||||
|
||||
* Compression levels 7, 8 and 9 favor compression ratio over speed.
|
||||
|
||||
* Compression level --best may take a long time.
|
||||
|
||||
Note that compression level --best can be somewhat slow for large files,
|
||||
but you definitely should use it when releasing a final version of your
|
||||
program.
|
||||
|
||||
Quick info for achieving the best compression ratio:
|
||||
|
||||
* Try upx --brute --no-lzma myfile.exe or even upx --ultra-brute
|
||||
--no-lzma myfile.exe.
|
||||
|
||||
* The option --lzma enables LZMA compression, which compresses better
|
||||
but is *significantly slower* at decompression. You probably do not
|
||||
want to use it for large files.
|
||||
|
||||
(Note that --lzma is automatically enabled by --all-methods and
|
||||
--brute, use --no-lzma to override.)
|
||||
|
||||
* Try if --overlay=strip works.
|
||||
|
||||
* For win32/pe programs there's --strip-relocs=0. See notes below.
|
||||
|
||||
OVERLAY HANDLING OPTIONS
|
||||
Info: An "overlay" means auxiliary data attached after the logical end
|
||||
of an executable, and it often contains application specific data (this
|
||||
is a common practice to avoid an extra data file, though it would be
|
||||
better to use resource sections).
|
||||
|
||||
UPX handles overlays like many other executable packers do: it simply
|
||||
copies the overlay after the compressed image. This works with some
|
||||
files, but doesn't work with others, depending on how an application
|
||||
actually accesses this overlayed data.
|
||||
|
||||
--overlay=copy Copy any extra data attached to the file. [DEFAULT]
|
||||
|
||||
--overlay=strip Strip any overlay from the program instead of
|
||||
copying it. Be warned, this may make the compressed
|
||||
program crash or otherwise unusable.
|
||||
|
||||
--overlay=skip Refuse to compress any program which has an overlay.
|
||||
|
||||
ENVIRONMENT VARIABLE
|
||||
The environment variable UPX can hold a set of default options for 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#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.
|
||||
|
||||
Not all of the options are valid in the environment variable - UPX will
|
||||
tell you.
|
||||
|
||||
You can explicitly use the --no-env option to ignore the environment
|
||||
variable.
|
||||
|
||||
NOTES FOR THE SUPPORTED EXECUTABLE FORMATS
|
||||
NOTES FOR ATARI/TOS
|
||||
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 :-). See https://freemint.github.io for
|
||||
more info.
|
||||
|
||||
Packed programs will be byte-identical to the original after
|
||||
uncompression. All debug information will be stripped, though.
|
||||
|
||||
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.
|
||||
|
||||
NOTES FOR BVMLINUZ/I386
|
||||
Same as vmlinuz/i386.
|
||||
|
||||
NOTES FOR DOS/COM
|
||||
Obviously 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+.
|
||||
|
||||
Packed programs will be byte-identical to the original after
|
||||
uncompression.
|
||||
|
||||
Maximum uncompressed size: ~65100 bytes.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
themselves (like some command line utilities that ship with
|
||||
Win95/98/ME).
|
||||
|
||||
Compressed programs only work on a 286+.
|
||||
|
||||
Extra options available for this executable format:
|
||||
|
||||
--8086 Create an executable that works on any 8086 CPU.
|
||||
|
||||
--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.
|
||||
|
||||
NOTES FOR DOS/SYS
|
||||
Compressed programs only work on a 286+.
|
||||
|
||||
Packed programs will be byte-identical to the original after
|
||||
uncompression.
|
||||
|
||||
Maximum uncompressed size: ~65350 bytes.
|
||||
|
||||
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.
|
||||
|
||||
NOTES FOR DJGPP2/COFF
|
||||
First of all, it is recommended to use UPX *instead* of 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
|
||||
will fix the 4 KiB alignment of the stub.
|
||||
|
||||
UPX includes the full functionality of stubify. This means it will
|
||||
automatically stubify your COFF files. Use the option --coff to disable
|
||||
this functionality (see below).
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
NOTES FOR LINUX [general]
|
||||
Introduction
|
||||
|
||||
Linux/386 support in UPX consists of 3 different executable formats,
|
||||
one optimized for ELF executables ("linux/elf386"), one optimized
|
||||
for shell scripts ("linux/sh386"), and one generic format
|
||||
("linux/386").
|
||||
|
||||
We will start with a general discussion first, but please
|
||||
also read the relevant docs for each of the individual formats.
|
||||
|
||||
Also, there is special support for bootable kernels - see the
|
||||
description of the vmlinuz/386 format.
|
||||
|
||||
General user's overview
|
||||
|
||||
Running a compressed executable program trades less space on a
|
||||
``permanent'' storage medium (such as a hard disk, floppy disk,
|
||||
CD-ROM, flash memory, EPROM, etc.) for more space in one or more
|
||||
``temporary'' storage media (such as RAM, swap space, /tmp, etc.).
|
||||
Running a compressed executable also requires some additional CPU
|
||||
cycles to generate the compressed executable in the first place,
|
||||
and to decompress it at each invocation.
|
||||
|
||||
How much space is traded? It depends on the executable, but many
|
||||
programs save 30% to 50% of permanent disk space. How much CPU
|
||||
overhead is there? Again, it depends on the executable, but
|
||||
decompression speed generally is at least many megabytes per second,
|
||||
and frequently is limited by the speed of the underlying disk
|
||||
or network I/O.
|
||||
|
||||
Depending on the statistics of usage and access, and the relative
|
||||
speeds of CPU, RAM, swap space, /tmp, and file system storage, then
|
||||
invoking and running a compressed executable can be faster than
|
||||
directly running the corresponding uncompressed program.
|
||||
The operating system might perform fewer expensive I/O operations
|
||||
to invoke the compressed program. Paging to or from swap space
|
||||
or /tmp might be faster than paging from the general file system.
|
||||
``Medium-sized'' programs which access about 1/3 to 1/2 of their
|
||||
stored program bytes can do particularly well with compression.
|
||||
Small programs tend not to benefit as much because the absolute
|
||||
savings is less. Big programs tend not to benefit proportionally
|
||||
because each invocation may use only a small fraction of the program,
|
||||
yet UPX decompresses the entire program before invoking it.
|
||||
But in environments where disk or flash memory storage is limited,
|
||||
then compression may win anyway.
|
||||
|
||||
Currently, executables compressed by UPX do not share RAM at runtime
|
||||
in the way that executables mapped from a file system do. As a
|
||||
result, if the same program is run simultaneously by more than one
|
||||
process, then using the compressed version will require more RAM and/or
|
||||
swap space. So, shell programs (bash, csh, etc.) and ``make''
|
||||
might not be good candidates for compression.
|
||||
|
||||
UPX recognizes three executable formats for Linux: Linux/elf386,
|
||||
Linux/sh386, and Linux/386. Linux/386 is the most generic format;
|
||||
it accommodates any file that can be executed. At runtime, the UPX
|
||||
decompression stub re-creates in /tmp a copy of the original file,
|
||||
and then the copy is (re-)executed with the same arguments.
|
||||
ELF binary executables prefer the Linux/elf386 format by default,
|
||||
because UPX decompresses them directly into RAM, uses only one
|
||||
exec, does not use space in /tmp, and does not use /proc.
|
||||
Shell scripts where the underlying shell accepts a ``-c'' argument
|
||||
can use the Linux/sh386 format. 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''.
|
||||
|
||||
General benefits:
|
||||
|
||||
- UPX can compress all executables, be it AOUT, ELF, libc4, libc5,
|
||||
libc6, Shell/Perl/Python/... scripts, standalone Java .class
|
||||
binaries, or whatever...
|
||||
All scripts and programs will work just as before.
|
||||
|
||||
- Compressed programs are completely self-contained. No need for
|
||||
any external program.
|
||||
|
||||
- UPX keeps your original program untouched. This means that
|
||||
after decompression you will have a byte-identical version,
|
||||
and you can use UPX as a file compressor just like gzip.
|
||||
[ Note that UPX maintains a checksum of the file internally,
|
||||
so it is indeed a reliable alternative. ]
|
||||
|
||||
- As the stub only uses syscalls and isn't linked against libc it
|
||||
should run under any Linux configuration that can run ELF
|
||||
binaries.
|
||||
|
||||
- For the same reason compressed executables should run under
|
||||
FreeBSD and other systems which can run Linux binaries.
|
||||
[ Please send feedback on this topic ]
|
||||
|
||||
General drawbacks:
|
||||
|
||||
- It is not advisable to compress programs which usually have many
|
||||
instances running (like `sh' or `make') because the common segments of
|
||||
compressed programs won't be shared any longer between different
|
||||
processes.
|
||||
|
||||
- `ldd' and `size' won't show anything useful because all they
|
||||
see is the statically linked stub. Since version 0.82 the section
|
||||
headers are stripped from the UPX stub and `size' doesn't even
|
||||
recognize the file format. The file patches/patch-elfcode.h has a
|
||||
patch to fix this bug in `size' and other programs which use GNU BFD.
|
||||
|
||||
General notes:
|
||||
|
||||
- As UPX leaves your original program untouched it is advantageous
|
||||
to strip it before compression.
|
||||
|
||||
- If you compress a script you will lose platform independence -
|
||||
this could be a problem if you are using NFS mounted disks.
|
||||
|
||||
- Compression of suid, guid and sticky-bit programs is rejected
|
||||
because of possible security implications.
|
||||
|
||||
- For the same reason there is no sense in making any compressed
|
||||
program suid.
|
||||
|
||||
- Obviously UPX won't work with executables that want to read data
|
||||
from themselves. E.g., this might be a problem for Perl scripts
|
||||
which access their __DATA__ lines.
|
||||
|
||||
- In case of internal errors the stub will abort with exitcode 127.
|
||||
Typical reasons for this to happen are that the program has somehow
|
||||
been modified after compression.
|
||||
Running `strace -o strace.log compressed_file' will tell you more.
|
||||
|
||||
NOTES FOR LINUX/ELF386
|
||||
Please read the general Linux description first.
|
||||
|
||||
The linux/elf386 format decompresses directly into RAM, uses only one
|
||||
exec, does not use space in /tmp, and does not use /proc.
|
||||
|
||||
Linux/elf386 is automatically selected for Linux ELF executables.
|
||||
|
||||
Packed programs will be byte-identical to the original after
|
||||
uncompression.
|
||||
|
||||
How it works:
|
||||
|
||||
For ELF executables, UPX decompresses directly to memory, simulating
|
||||
the mapping that the operating system kernel uses during exec(),
|
||||
including the PT_INTERP program interpreter (if any).
|
||||
The brk() is set by a special PT_LOAD segment in the compressed
|
||||
executable itself. UPX then wipes the stack clean except for
|
||||
arguments, environment variables, and Elf_auxv entries (this is
|
||||
required by bugs in the startup code of /lib/ld-linux.so as of
|
||||
May 2000), and transfers control to the program interpreter or
|
||||
the e_entry address of the original executable.
|
||||
|
||||
The UPX stub is about 1700 bytes long, partly written in assembler
|
||||
and only uses kernel syscalls. It is not linked against any libc.
|
||||
|
||||
Specific drawbacks:
|
||||
|
||||
- For linux/elf386 and linux/sh386 formats, you will be relying on
|
||||
RAM and swap space to hold all of the decompressed program during
|
||||
the lifetime of the process. If you already use most of your swap
|
||||
space, then you may run out. A system that is "out of memory"
|
||||
can become fragile. Many programs do not react gracefully when
|
||||
malloc() returns 0. With newer Linux kernels, the kernel
|
||||
may decide to kill some processes to regain memory, and you
|
||||
may not like the kernel's choice of which to kill. Running
|
||||
/usr/bin/top is one way to check on the usage of swap space.
|
||||
|
||||
Extra options available for this executable format:
|
||||
|
||||
(none)
|
||||
|
||||
NOTES FOR LINUX/SH386
|
||||
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 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.
|
||||
|
||||
Linux/sh386 is automatically selected for shell scripts that use a known
|
||||
shell.
|
||||
|
||||
Packed programs will be byte-identical to the original after
|
||||
uncompression.
|
||||
|
||||
How it works:
|
||||
|
||||
For shell script executables (files beginning with "#!/" or "#! /")
|
||||
where the shell is known to accept "-c <command>", UPX decompresses
|
||||
the file into low memory, then maps the shell (and its PT_INTERP),
|
||||
and passes control to the shell with the entire decompressed file
|
||||
as the argument after "-c". Known shells are sh, ash, bash, bsh, csh,
|
||||
ksh, tcsh, pdksh. Restriction: UPX cannot use this method
|
||||
for shell scripts which use the one optional string argument after
|
||||
the shell name in the script (example: "#! /bin/sh option3\n".)
|
||||
|
||||
The UPX stub is about 1700 bytes long, partly written in assembler
|
||||
and only uses kernel syscalls. It is not linked against any libc.
|
||||
|
||||
Specific drawbacks:
|
||||
|
||||
- For linux/elf386 and linux/sh386 formats, you will be relying on
|
||||
RAM and swap space to hold all of the decompressed program during
|
||||
the lifetime of the process. If you already use most of your swap
|
||||
space, then you may run out. A system that is "out of memory"
|
||||
can become fragile. Many programs do not react gracefully when
|
||||
malloc() returns 0. With newer Linux kernels, the kernel
|
||||
may decide to kill some processes to regain memory, and you
|
||||
may not like the kernel's choice of which to kill. Running
|
||||
/usr/bin/top is one way to check on the usage of swap space.
|
||||
|
||||
Extra options available for this executable format:
|
||||
|
||||
(none)
|
||||
|
||||
NOTES FOR LINUX/386
|
||||
Please read the general Linux description first.
|
||||
|
||||
The generic linux/386 format decompresses to /tmp and needs /proc file
|
||||
system 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.
|
||||
|
||||
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 execve(), which first requires decompressing to a
|
||||
temporary file in the file system. Interestingly -
|
||||
because of the good memory management of the Linux kernel - this
|
||||
often does not introduce a noticeable delay, and in fact there
|
||||
will be no disk access at all if you have enough free memory as
|
||||
the entire process takes places within the file system buffers.
|
||||
|
||||
A compressed executable consists of the UPX stub and an overlay
|
||||
which contains the original program in a compressed form.
|
||||
|
||||
The UPX stub is a statically linked ELF executable and does
|
||||
the following at program startup:
|
||||
|
||||
1) decompress the overlay to a temporary location in /tmp
|
||||
2) open the temporary file for reading
|
||||
3) try to delete the temporary file and start (execve)
|
||||
the uncompressed program in /tmp using /proc/<pid>/fd/X as
|
||||
attained by step 2)
|
||||
4) if that fails, fork off a subprocess to clean up and
|
||||
start the program in /tmp in the meantime
|
||||
|
||||
The UPX stub is about 1700 bytes long, partly written in assembler
|
||||
and only uses kernel syscalls. It is not linked against any libc.
|
||||
|
||||
Specific drawbacks:
|
||||
|
||||
- You need additional free disk space for the uncompressed program
|
||||
in your /tmp directory. This program is deleted immediately after
|
||||
decompression, but you still need it for the full execution time
|
||||
of the program.
|
||||
|
||||
- You must have /proc file system support as the stub wants to open
|
||||
/proc/<pid>/exe and needs /proc/<pid>/fd/X. This also means that you
|
||||
cannot compress programs that are used during the boot sequence
|
||||
before /proc is mounted.
|
||||
|
||||
- Utilities like `top' will display numerical values in the process
|
||||
name field. This is because Linux computes the process name from
|
||||
the first argument of the last execve syscall (which is typically
|
||||
something like /proc/<pid>/fd/3).
|
||||
|
||||
- Because of temporary decompression to disk the decompression speed
|
||||
is not as fast as with the other executable formats. Still, I can see
|
||||
no noticeable delay when starting programs like my ~3 MiB emacs (which
|
||||
is less than 1 MiB when compressed :-).
|
||||
|
||||
Extra options available for this executable format:
|
||||
|
||||
--force-execve Force the use of the generic linux/386 "execve"
|
||||
format, i.e. do not try the linux/elf386 and
|
||||
linux/sh386 formats.
|
||||
|
||||
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.
|
||||
|
||||
Packed programs will be byte-identical to the original after
|
||||
uncompression, until further notice.
|
||||
|
||||
Maximum uncompressed size: ~1.89 / ~7.60 MiB.
|
||||
|
||||
Notes:
|
||||
|
||||
- UPX creates as default a suitable executable for CD-Mastering
|
||||
and console transfer. For a CD-Master main executable you could also try
|
||||
the special option "--boot-only" as described below.
|
||||
It has been reported that upx packed executables are fully compatible with
|
||||
the Sony PlayStation 2 (PS2, PStwo) and Sony PlayStation Portable (PSP) in
|
||||
Sony PlayStation (PSone) emulation mode.
|
||||
|
||||
- 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 relocate the loading address
|
||||
for the packed file, but this isn't a real problem if it is a single or
|
||||
the main 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.
|
||||
|
||||
--8-bit Uses 8 bit size compression [default: 32 bit]
|
||||
|
||||
--8mib-ram PSone has 8 MiB ram available [default: 2 MiB]
|
||||
|
||||
--boot-only This format is for main exes and CD-Mastering only !
|
||||
It may slightly improve the compression ratio,
|
||||
decompression routines are faster than default ones.
|
||||
But it cannot be used for console transfer !
|
||||
|
||||
--no-align This option disables CD mode 2 data sector format
|
||||
alignment. May slightly improves the compression ratio,
|
||||
but the compressed executable will not boot from a CD.
|
||||
Use it for console transfer only !
|
||||
|
||||
NOTES FOR RTM32/PE and ARM/PE
|
||||
Same as win32/pe.
|
||||
|
||||
NOTES FOR TMT/ADAM
|
||||
This format is used by the TMT Pascal compiler - see http://www.tmt.com/
|
||||
.
|
||||
|
||||
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.
|
||||
|
||||
--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.
|
||||
|
||||
NOTES FOR VMLINUZ/386
|
||||
The vmlinuz/386 and bvmlinuz/386 formats take a gzip-compressed bootable
|
||||
Linux kernel image ("vmlinuz", "zImage", "bzImage"), gzip-decompress it
|
||||
and re-compress it with the UPX compression method.
|
||||
|
||||
vmlinuz/386 is completely unrelated to the other Linux executable
|
||||
formats, and it does not share any of their drawbacks.
|
||||
|
||||
Notes:
|
||||
|
||||
- Be sure that "vmlinuz/386" or "bvmlinuz/386" is displayed
|
||||
during compression - otherwise a wrong executable format
|
||||
may have been used, and the kernel won't boot.
|
||||
|
||||
Benefits:
|
||||
|
||||
- Better compression (but note that the kernel was already compressed,
|
||||
so the improvement is not as large as with other formats).
|
||||
Still, the bytes saved may be essential for special needs like
|
||||
boot disks.
|
||||
|
||||
For example, this is what I get for my 2.2.16 kernel:
|
||||
1589708 vmlinux
|
||||
641073 bzImage [original]
|
||||
560755 bzImage.upx [compressed by "upx -9"]
|
||||
|
||||
- Much faster decompression at kernel boot time (but kernel
|
||||
decompression speed is not really an issue these days).
|
||||
|
||||
Drawbacks:
|
||||
|
||||
(none)
|
||||
|
||||
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.
|
||||
|
||||
--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.
|
||||
|
||||
NOTES FOR WATCOM/LE
|
||||
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).
|
||||
|
||||
DLLs and the LX format are not supported.
|
||||
|
||||
Extra options available for this executable format:
|
||||
|
||||
--le Produce an unbound LE output instead of
|
||||
keeping the current stub.
|
||||
|
||||
NOTES FOR WIN32/PE
|
||||
The PE support in UPX is quite stable now, but probably there are still
|
||||
some incompatibilities with some files.
|
||||
|
||||
Because of the way UPX (and other packers for this format) works, you
|
||||
can see increased memory usage of your compressed files because the
|
||||
whole program is loaded into memory at startup. If you start several
|
||||
instances of huge compressed programs you're wasting memory because the
|
||||
common segments of the program won't get shared across the instances. On
|
||||
the other hand if you're compressing only smaller programs, or running
|
||||
only one instance of larger programs, then this penalty is smaller, but
|
||||
it's still there.
|
||||
|
||||
If you're running executables from network, then compressed programs
|
||||
will load faster, and require less bandwidth during execution.
|
||||
|
||||
DLLs are supported. But UPX compressed DLLs can not share common data
|
||||
and code when they got used by multiple applications. So compressing
|
||||
msvcrt.dll is a waste of memory, but compressing the dll plugins of a
|
||||
particular application may be a better idea.
|
||||
|
||||
Screensavers are supported, with the restriction that the filename must
|
||||
end with ".scr" (as screensavers are handled slightly different than
|
||||
normal exe files).
|
||||
|
||||
UPX compressed PE files have some minor memory overhead (usually in the
|
||||
10 - 30 KiB range) which can be seen by specifying the "-i" command line
|
||||
switch during compression.
|
||||
|
||||
Extra options available for this executable format:
|
||||
|
||||
--compress-exports=0 Don't compress the export section.
|
||||
Use this if you plan to run the compressed
|
||||
program under Wine.
|
||||
--compress-exports=1 Compress the export section. [DEFAULT]
|
||||
Compression of the export section can improve the
|
||||
compression ratio quite a bit but may not work
|
||||
with all programs (like winword.exe).
|
||||
UPX never compresses the export section of a DLL
|
||||
regardless of this option.
|
||||
|
||||
--compress-icons=0 Don't compress any icons.
|
||||
--compress-icons=1 Compress all but the first icon.
|
||||
--compress-icons=2 Compress all icons which are not in the
|
||||
first icon directory. [DEFAULT]
|
||||
--compress-icons=3 Compress all icons.
|
||||
|
||||
--compress-resources=0 Don't compress any resources at all.
|
||||
|
||||
--keep-resource=list Don't compress resources specified by the list.
|
||||
The members of the list are separated by commas.
|
||||
A list member has the following format: I<type[/name]>.
|
||||
I<Type> is the type of the resource. Standard types
|
||||
must be specified as decimal numbers, user types can be
|
||||
specified by decimal IDs or strings. I<Name> is the
|
||||
identifier of the resource. It can be a decimal number
|
||||
or a string. For example:
|
||||
|
||||
--keep-resource=2/MYBITMAP,5,6/12345
|
||||
|
||||
UPX won't compress the named bitmap resource "MYBITMAP",
|
||||
it leaves every dialog (5) resource uncompressed, and
|
||||
it won't touch the string table resource with identifier
|
||||
12345.
|
||||
|
||||
--force Force compression even when there is an
|
||||
unexpected value in a header field.
|
||||
Use with care.
|
||||
|
||||
--strip-relocs=0 Don't strip relocation records.
|
||||
--strip-relocs=1 Strip relocation records. [DEFAULT]
|
||||
This option only works on executables with base
|
||||
address greater or equal to 0x400000. Usually the
|
||||
compressed files becomes smaller, but some files
|
||||
may become larger. Note that the resulting file will
|
||||
not work under Windows 3.x (Win32s).
|
||||
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.
|
||||
|
||||
DIAGNOSTICS
|
||||
Exit status is normally 0; if an error occurs, exit status is 1. If a
|
||||
warning occurs, exit status is 2.
|
||||
|
||||
UPX's diagnostics are intended to be self-explanatory.
|
||||
|
||||
BUGS
|
||||
Please report all bugs immediately to the authors.
|
||||
|
||||
AUTHORS
|
||||
Markus F.X.J. Oberhumer <markus@oberhumer.com>
|
||||
http://www.oberhumer.com
|
||||
|
||||
Laszlo Molnar <ezerotven+github@gmail.com>
|
||||
|
||||
John F. Reiser <jreiser@BitWagon.com>
|
||||
|
||||
Jens Medoch <jssg@users.sourceforge.net>
|
||||
|
||||
COPYRIGHT
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
|
||||
Copyright (C) 2000-2023 John F. Reiser
|
||||
|
||||
Copyright (C) 2002-2023 Jens Medoch
|
||||
|
||||
UPX is distributed with full source code under the terms of the GNU
|
||||
General Public License v2+; either under the pure GPLv2+ (see the file
|
||||
COPYING), or (at your option) under the GPLv+2 with special exceptions
|
||||
and restrictions granting the free usage for all binaries including
|
||||
commercial programs (see the file LICENSE).
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the UPX License Agreements along with
|
||||
this program; see the files COPYING and LICENSE. If not, visit the UPX
|
||||
home page.
|
||||
|
||||
+61
-60
@@ -13,8 +13,8 @@ B<upx> S<[ I<command> ]> S<[ I<options> ]> I<filename>...
|
||||
=head1 ABSTRACT
|
||||
|
||||
The Ultimate Packer for eXecutables
|
||||
Copyright (c) 1996-2008 Markus Oberhumer, Laszlo Molnar & John Reiser
|
||||
http://upx.sourceforge.net
|
||||
Copyright (c) 1996-2023 Markus Oberhumer, Laszlo Molnar & John Reiser
|
||||
https://upx.github.io
|
||||
|
||||
|
||||
B<UPX> is a portable, extendable, high-performance executable packer for
|
||||
@@ -23,74 +23,59 @@ ratio and offers I<*very*> fast decompression. Your executables suffer
|
||||
no memory overhead or other drawbacks for most of the formats supported,
|
||||
because of in-place decompression.
|
||||
|
||||
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 B<UPX> and ourselves in the documentation,
|
||||
possibly including a reference to the B<UPX> home page. Thanks.
|
||||
|
||||
[ Using B<UPX> in non-OpenSource applications without proper credits
|
||||
is considered not politically correct ;-) ]
|
||||
|
||||
|
||||
|
||||
=head1 DISCLAIMER
|
||||
|
||||
B<UPX> comes with ABSOLUTELY NO WARRANTY; for details see the file LICENSE.
|
||||
|
||||
This is the first production quality release, and we plan that future 1.xx
|
||||
releases will be backward compatible with this version.
|
||||
B<UPX> comes with ABSOLUTELY NO WARRANTY; for details see the file COPYING.
|
||||
|
||||
Please report all problems or suggestions to the authors. Thanks.
|
||||
|
||||
|
||||
|
||||
=head1 SECURITY CONTEXT
|
||||
|
||||
IMPORTANT NOTE: B<UPX> inherits the security context of any files it handles.
|
||||
|
||||
This means that packing, unpacking, or even testing or listing a file requires
|
||||
the same security considerations as actually executing the file.
|
||||
|
||||
Use B<UPX> on trusted files only!
|
||||
|
||||
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<UPX> is a versatile executable packer with the following features:
|
||||
|
||||
- excellent compression ratio: compresses better than zip/gzip,
|
||||
- secure: as UPX is documented Open Source since many years any relevant
|
||||
Security/Antivirus software is able to peek inside UPX compressed
|
||||
apps to verify them
|
||||
|
||||
- excellent compression ratio: typically compresses better than Zip,
|
||||
use UPX to decrease the size of your distribution !
|
||||
|
||||
- very fast decompression: about 10 MiB/sec on an ancient Pentium 133,
|
||||
about 200 MiB/sec on an Athlon XP 2000+.
|
||||
- very fast decompression: more than 500 MB/sec on any reasonably modern
|
||||
machine
|
||||
|
||||
- no memory overhead for your compressed executables for most of the
|
||||
supported formats
|
||||
supported formats because of in-place decompression
|
||||
|
||||
- safe: you can list, test and unpack your executables
|
||||
- safe: you can list, test and unpack your executables.
|
||||
Also, a checksum of both the compressed and uncompressed file is
|
||||
maintained internally.
|
||||
|
||||
- universal: UPX can pack a number of executable formats:
|
||||
* atari/tos
|
||||
* bvmlinuz/386 [bootable Linux kernel]
|
||||
* djgpp2/coff
|
||||
* dos/com
|
||||
* dos/exe
|
||||
* dos/sys
|
||||
* linux/386
|
||||
* linux/elf386
|
||||
* linux/sh386
|
||||
* ps1/exe
|
||||
* rtm32/pe
|
||||
* tmt/adam
|
||||
* vmlinuz/386 [bootable Linux kernel]
|
||||
* vmlinux/386
|
||||
* watcom/le (supporting DOS4G, PMODE/W, DOS32a and CauseWay)
|
||||
* win32/pe (exe and dll)
|
||||
* arm/pe (exe and dll)
|
||||
* linux/elfamd64
|
||||
* linux/elfppc32
|
||||
* mach/elfppc32
|
||||
- universal: UPX can pack a number of executable formats, including
|
||||
Windows programs and DLLs, macOS apps and Linux executables
|
||||
|
||||
- portable: UPX is written in portable endian-neutral C++
|
||||
|
||||
- extendable: because of the class layout it's very easy to support
|
||||
new executable formats or add new compression algorithms
|
||||
|
||||
- free: UPX can be distributed and used freely. And from version 0.99
|
||||
the full source code of UPX is released under the GNU General Public
|
||||
License (GPL) !
|
||||
- free: UPX is distributed with full source code under the GNU General
|
||||
Public License v2+, with special exceptions granting the free usage
|
||||
for commercial programs
|
||||
|
||||
You probably understand now why we call B<UPX> the "I<ultimate>"
|
||||
executable packer.
|
||||
@@ -145,7 +130,11 @@ compress and then decompress your program a first time - any further
|
||||
compress-decompress steps should then yield byte-identical results
|
||||
as compared to the first decompressed version.]
|
||||
|
||||
[ ...to be written... - type `B<upx --help>' for now ]
|
||||
B<-k>: keep backup files
|
||||
|
||||
B<-o file>: write output to file
|
||||
|
||||
[ ...more docs need to be written... - type `B<upx --help>' for now ]
|
||||
|
||||
|
||||
|
||||
@@ -185,7 +174,17 @@ Quick info for achieving the best compression ratio:
|
||||
|
||||
=item *
|
||||
|
||||
Try B<upx --brute myfile.exe> or even B<upx --ultra-brute myfile.exe>.
|
||||
Try B<upx --brute --no-lzma myfile.exe> or even
|
||||
B<upx --ultra-brute --no-lzma myfile.exe>.
|
||||
|
||||
=item *
|
||||
|
||||
The option B<--lzma> enables LZMA compression, which compresses better but
|
||||
is *significantly slower* at decompression. You probably do not want
|
||||
to use it for large files.
|
||||
|
||||
(Note that B<--lzma> is automatically enabled by B<--all-methods> and
|
||||
B<--brute>, use B<--no-lzma> to override.)
|
||||
|
||||
=item *
|
||||
|
||||
@@ -221,7 +220,7 @@ actually accesses this overlayed data.
|
||||
|
||||
|
||||
|
||||
=head1 ENVIRONMENT
|
||||
=head1 ENVIRONMENT VARIABLE
|
||||
|
||||
The environment variable B<UPX> can hold a set of default
|
||||
options for B<UPX>. These options are interpreted first and
|
||||
@@ -251,7 +250,7 @@ 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 :-).
|
||||
See http://www.freemint.de for more info.
|
||||
See https://freemint.github.io for more info.
|
||||
|
||||
Packed programs will be byte-identical to the original after uncompression.
|
||||
All debug information will be stripped, though.
|
||||
@@ -674,7 +673,7 @@ Extra options available for this executable format:
|
||||
=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.
|
||||
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.
|
||||
|
||||
@@ -923,7 +922,7 @@ Please report all bugs immediately to the authors.
|
||||
Markus F.X.J. Oberhumer <markus@oberhumer.com>
|
||||
http://www.oberhumer.com
|
||||
|
||||
Laszlo Molnar <ml1050@users.sourceforge.net>
|
||||
Laszlo Molnar <ezerotven+github@gmail.com>
|
||||
|
||||
John F. Reiser <jreiser@BitWagon.com>
|
||||
|
||||
@@ -933,22 +932,24 @@ Please report all bugs immediately to the authors.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
|
||||
Copyright (C) 2000-2008 John F. Reiser
|
||||
Copyright (C) 2000-2023 John F. Reiser
|
||||
|
||||
Copyright (C) 2002-2008 Jens Medoch
|
||||
Copyright (C) 2002-2023 Jens Medoch
|
||||
|
||||
This program may be used freely, and you are welcome to
|
||||
redistribute it under certain conditions.
|
||||
B<UPX> is distributed with full source code under the terms of the
|
||||
GNU General Public License v2+; either under the pure GPLv2+ (see
|
||||
the file COPYING), or (at your option) under the GPLv+2 with special
|
||||
exceptions and restrictions granting the free usage for all binaries
|
||||
including commercial programs (see the file LICENSE).
|
||||
|
||||
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
|
||||
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.
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
You should have received a copy of the UPX License Agreements along
|
||||
with this program; see the files COPYING and LICENSE. If not,
|
||||
visit the UPX home page.
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
#! /usr/bin/env bash
|
||||
## vim:set ts=4 sw=4 et:
|
||||
set -e; set -o pipefail
|
||||
argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
|
||||
|
||||
# create the image from Dockerfile
|
||||
# using a rootless Podman container
|
||||
|
||||
# NOTE: this image is based on rebuild-stubs-with-podman/upx-stubtools-20221212-v4,
|
||||
# so you have to create that image first
|
||||
# WARNING: we install many packages, so the resulting image needs A LOT of disk space!
|
||||
image=upx-cross-compile-20230115-v2
|
||||
|
||||
podman build -t "$image" -f "$argv0dir/Dockerfile" "$argv0dir"
|
||||
|
||||
podman image list "$image"
|
||||
podman image tree "$image"
|
||||
@@ -0,0 +1,53 @@
|
||||
#! /usr/bin/env bash
|
||||
## vim:set ts=4 sw=4 et:
|
||||
set -e; set -o pipefail
|
||||
argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
|
||||
|
||||
# run an interactive shell in the image
|
||||
# using a rootless Podman container
|
||||
|
||||
image=upx-cross-compile-20230115-v2
|
||||
|
||||
flags=( -ti --read-only --rm )
|
||||
flags+=( --cap-drop=all ) # drop all capabilities
|
||||
flags+=( --network=none ) # no network needed
|
||||
flags+=( -e TERM="$TERM" ) # pass $TERM
|
||||
if [[ 1 == 1 ]]; then
|
||||
# run as user upx 2000:2000
|
||||
flags+=( --user 2000 )
|
||||
# map container users 0..999 to subuid-users 1..1000, and map container user 2000 to current host user
|
||||
flags+=( --uidmap=0:1:1000 --uidmap=2000:0:1 )
|
||||
# map container groups 0..999 to subgid-groups 1..1000, and map container group 2000 to current host group
|
||||
flags+=( --gidmap=0:1:1000 --gidmap=2000:0:1 )
|
||||
# NOTE: we mount the upx top-level directory read-write under /home/upx/src/upx
|
||||
# INFO: SELinux users *may* have to add ":z" to the volume mount flags; check the docs!
|
||||
flags+=( -v "${argv0dir}/../..:/home/upx/src/upx" )
|
||||
flags+=( -w /home/upx/src/upx ) # set working directory
|
||||
else
|
||||
# run as user root 0:0
|
||||
# ONLY FOR DEBUGGING THE IMAGE
|
||||
# map container user/group 0 to current host user/group
|
||||
flags+=( --user 0 )
|
||||
fi
|
||||
|
||||
podman run "${flags[@]}" "$image" bash -l
|
||||
|
||||
# now we can cross-compile UPX for Windows:
|
||||
# cd /home/upx/src/upx
|
||||
# rm -rf ./build/extra/cross-windows-mingw64/release
|
||||
# make build/extra/cross-windows-mingw64/release
|
||||
|
||||
# and we can run the clang Static Analyzer (scan-build)
|
||||
# cd /home/upx/src/upx
|
||||
# rm -rf ./build/extra/scan-build/release
|
||||
# make build/extra/scan-build/release
|
||||
|
||||
# and lots of other cross-compilers are installed; see "ls /usr/bin/*g++*"
|
||||
|
||||
# and finally see misc/cross-compile-upx-with-podman/build-all-inside-container.sh
|
||||
# after running that script we can do cool things like:
|
||||
# cd /home/upx/src/upx/build/cross-compile-upx-with-podman/alpha-linux-gnu/debug
|
||||
# qemu-alpha -L /usr/alpha-linux-gnu upx --version
|
||||
# cd /home/upx/src/upx/build/cross-compile-upx-with-podman/hppa-linux-gnu/debug
|
||||
# qemu-hppa -L /usr/hppa-linux-gnu upx --version
|
||||
# (similar for many other architectures/builds)
|
||||
@@ -0,0 +1,54 @@
|
||||
# NOTE: this image is based on rebuild-stubs-with-podman/upx-stubtools-20221212-v4,
|
||||
# so you have to create that image first
|
||||
# WARNING: we install many packages, so the resulting image needs A LOT of disk space!
|
||||
FROM localhost/upx-stubtools-20221212-v4
|
||||
ENV UPX_CONTAINER_IMAGE_NAME=upx-cross-compile-20230115-v2
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
USER root
|
||||
|
||||
# Ubuntu 22.04
|
||||
RUN apt-get update && apt-get upgrade -y \
|
||||
&& apt-get install -y \
|
||||
# Linux glibc cross compilers
|
||||
g++-aarch64-linux-gnu \
|
||||
g++-alpha-linux-gnu \
|
||||
g++-arm-linux-gnueabi \
|
||||
g++-arm-linux-gnueabihf \
|
||||
g++-hppa-linux-gnu \
|
||||
g++-i686-linux-gnu \
|
||||
g++-m68k-linux-gnu \
|
||||
g++-mips-linux-gnu \
|
||||
g++-mipsel-linux-gnu \
|
||||
g++-mips64-linux-gnuabi64 \
|
||||
g++-mips64el-linux-gnuabi64 \
|
||||
g++-powerpc-linux-gnu \
|
||||
g++-powerpc64-linux-gnu \
|
||||
g++-powerpc64le-linux-gnu \
|
||||
g++-riscv64-linux-gnu \
|
||||
g++-s390x-linux-gnu \
|
||||
g++-sh4-linux-gnu \
|
||||
g++-sparc64-linux-gnu \
|
||||
# Linux glibc cross compilers - ILP32 on 64-bit CPUs
|
||||
g++-x86-64-linux-gnux32 \
|
||||
# Windows cross compilers
|
||||
g++-mingw-w64-i686 \
|
||||
g++-mingw-w64-x86-64 \
|
||||
&& true
|
||||
RUN apt-get install -y \
|
||||
# clang-14 and tools
|
||||
clang-14 clang-format-14 clang-tidy-14 clang-tools-14 lldb-14 llvm-14 \
|
||||
# QEMU and Wine
|
||||
qemu-system qemu-user wine wine32 \
|
||||
# misc
|
||||
gdb lsb-release valgrind \
|
||||
&& true
|
||||
RUN cd /usr/bin \
|
||||
# create unversioned clang symlinks in /usr/local/bin
|
||||
&& for f in clang*-14 llvm-*-14 scan-*-14; do ln -s -v ../../bin/$f /usr/local/bin/${f%-14}; done \
|
||||
&& ln -s -v ../../bin/obj2yaml-14 /usr/local/bin/llvm-obj2yaml \
|
||||
&& ln -s -v ../../bin/yaml2obj-14 /usr/local/bin/llvm-yaml2obj \
|
||||
&& true
|
||||
|
||||
# switch back to default user upx 2000:2000
|
||||
USER upx
|
||||
@@ -0,0 +1,93 @@
|
||||
#! /usr/bin/env bash
|
||||
## vim:set ts=4 sw=4 et:
|
||||
set -e; set -o pipefail
|
||||
argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
|
||||
|
||||
# build UPX for 21 targets; must be run inside the container!
|
||||
# using a rootless Podman container
|
||||
|
||||
# simple sanity check that we are indeed running inside the container
|
||||
if [[ $UPX_CONTAINER_IMAGE_NAME != upx-cross-compile-* ]]; then
|
||||
echo "$argv0: NOTE: please run this script *inside* the container"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# go to upx top-level directory
|
||||
cd "$argv0dir/../.." || exit 1
|
||||
pwd
|
||||
[[ -f src/version.h ]] || exit 1 # sanity check
|
||||
|
||||
function run_config_and_build {
|
||||
# requires: AR CC CXX RANLIB
|
||||
local toolchain=$1
|
||||
local cmake_config_flags build_type bdir
|
||||
# cmake flags
|
||||
cmake_config_flags=
|
||||
case $toolchain in
|
||||
# these old architectures do not support sanitize
|
||||
alpha-linux-gnu) cmake_config_flags=-DUPX_CONFIG_DISABLE_SANITIZE=ON ;;
|
||||
hppa-linux-gnu) cmake_config_flags=-DUPX_CONFIG_DISABLE_SANITIZE=ON ;;
|
||||
# avoid link errors with current MinGW-w64 versions
|
||||
i686-w64-mingw32) cmake_config_flags=-DUPX_CONFIG_DISABLE_SANITIZE=ON ;;
|
||||
x86_64-w64-mingw32) cmake_config_flags=-DUPX_CONFIG_DISABLE_SANITIZE=ON ;;
|
||||
# avoid warnings about arm libstdc++ ABI change in gcc-7
|
||||
arm-linux-*) CXX="$CXX -Wno-psabi" ;;
|
||||
esac
|
||||
if [[ 1 == 1 ]]; then
|
||||
# prefer building with Ninja (ninja-build)
|
||||
cmake_config_flags="$cmake_config_flags -G Ninja -DUPX_CONFIG_CMAKE_DISABLE_INSTALL=ON"
|
||||
fi
|
||||
# for all build types
|
||||
for build_type in Debug Release; do
|
||||
bdir=build/cross-compile-upx-with-podman/$toolchain/${build_type,,}
|
||||
mkdir -p $bdir
|
||||
# run_config
|
||||
if [[ ! -f $bdir/CMakeCache.txt ]]; then
|
||||
cmake -S . -B $bdir -DCMAKE_BUILD_TYPE=$build_type -DCMAKE_AR=$AR -DCMAKE_RANLIB=$RANLIB $cmake_config_flags
|
||||
fi
|
||||
# run_build
|
||||
cmake --build $bdir --config $build_type --parallel
|
||||
done
|
||||
}
|
||||
|
||||
# see Dockerfile for packages
|
||||
for package in \
|
||||
g++-aarch64-linux-gnu \
|
||||
g++-alpha-linux-gnu \
|
||||
g++-arm-linux-gnueabi \
|
||||
g++-arm-linux-gnueabihf \
|
||||
g++-hppa-linux-gnu \
|
||||
g++-i686-linux-gnu \
|
||||
g++-m68k-linux-gnu \
|
||||
g++-mips-linux-gnu \
|
||||
g++-mipsel-linux-gnu \
|
||||
g++-mips64-linux-gnuabi64 \
|
||||
g++-mips64el-linux-gnuabi64 \
|
||||
g++-powerpc-linux-gnu \
|
||||
g++-powerpc64-linux-gnu \
|
||||
g++-powerpc64le-linux-gnu \
|
||||
g++-riscv64-linux-gnu \
|
||||
g++-s390x-linux-gnu \
|
||||
g++-sh4-linux-gnu \
|
||||
g++-sparc64-linux-gnu \
|
||||
g++-x86-64-linux-gnux32 \
|
||||
g++-mingw-w64-i686 \
|
||||
g++-mingw-w64-x86-64
|
||||
do
|
||||
# setup toolchain and environment variables
|
||||
toolchain=$package
|
||||
toolchain=${toolchain/-x86-64/-x86_64}
|
||||
toolchain=${toolchain/g++-/}
|
||||
case $toolchain in
|
||||
mingw-w64-i686) toolchain=i686-w64-mingw32 ;;
|
||||
mingw-w64-x86_64) toolchain=x86_64-w64-mingw32 ;;
|
||||
esac
|
||||
echo "========== $toolchain"
|
||||
export AR=/usr/bin/${toolchain}-ar
|
||||
export CC=/usr/bin/${toolchain}-gcc
|
||||
export CXX=/usr/bin/${toolchain}-g++
|
||||
export RANLIB=/usr/bin/${toolchain}-ranlib
|
||||
ls -l $AR $CC $CXX $RANLIB
|
||||
run_config_and_build $toolchain
|
||||
unset AR CC CXX RANLIB
|
||||
done
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
#! /usr/bin/env bash
|
||||
## vim:set ts=4 sw=4 et:
|
||||
set -e; set -o pipefail
|
||||
argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
|
||||
|
||||
# create the image from Dockerfile
|
||||
# using a rootless Podman container
|
||||
|
||||
image=upx-stubtools-20221212-v4
|
||||
|
||||
podman build -t "$image" -f "$argv0dir/Dockerfile" "$argv0dir"
|
||||
|
||||
podman image list "$image"
|
||||
podman image tree "$image"
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
#! /usr/bin/env bash
|
||||
## vim:set ts=4 sw=4 et:
|
||||
set -e; set -o pipefail
|
||||
argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
|
||||
|
||||
# run an interactive shell in the image
|
||||
# using a rootless Podman container
|
||||
|
||||
image=upx-stubtools-20221212-v4
|
||||
|
||||
flags=( -ti --read-only --rm )
|
||||
flags+=( --cap-drop=all ) # drop all capabilities
|
||||
flags+=( --network=none ) # no network needed
|
||||
flags+=( -e TERM="$TERM" ) # pass $TERM
|
||||
if [[ 1 == 1 ]]; then
|
||||
# run as user upx 2000:2000
|
||||
flags+=( --user 2000 )
|
||||
# map container users 0..999 to subuid-users 1..1000, and map container user 2000 to current host user
|
||||
flags+=( --uidmap=0:1:1000 --uidmap=2000:0:1 )
|
||||
# map container groups 0..999 to subgid-groups 1..1000, and map container group 2000 to current host group
|
||||
flags+=( --gidmap=0:1:1000 --gidmap=2000:0:1 )
|
||||
# NOTE: we mount the upx top-level directory read-write under /home/upx/src/upx
|
||||
# INFO: SELinux users *may* have to add ":z" to the volume mount flags; check the docs!
|
||||
flags+=( -v "${argv0dir}/../..:/home/upx/src/upx" )
|
||||
flags+=( -w /home/upx/src/upx ) # set working directory
|
||||
else
|
||||
# run as user root 0:0
|
||||
# ONLY FOR DEBUGGING THE IMAGE
|
||||
# map container user/group 0 to current host user/group
|
||||
flags+=( --user 0 )
|
||||
fi
|
||||
|
||||
podman run "${flags[@]}" "$image" bash -l
|
||||
|
||||
# now we can rebuild the UPX stubs:
|
||||
# cd /home/upx/src/upx/src/stub
|
||||
# # make sure that git is clean:
|
||||
# git status .
|
||||
# # remove stub files and make sure that they got deleted:
|
||||
# make maintainer-clean extra-clean
|
||||
# git status .
|
||||
# # rebuild
|
||||
# make extra-all all
|
||||
# # make sure that the stub files did rebuild correctly:
|
||||
# git status .
|
||||
# git diff .
|
||||
|
||||
# we can also build UPX in the container:
|
||||
# cd /home/upx/src/upx
|
||||
# rm -rf ./build/extra/gcc/release
|
||||
# make build/extra/gcc/release
|
||||
# # run tests
|
||||
# ./build/extra/gcc/release/upx --version
|
||||
# make -C build/extra/gcc/release test
|
||||
|
||||
# and we can also build UPX with -m32:
|
||||
# cd /home/upx/src/upx
|
||||
# rm -rf ./build/extra/gcc-m32/release
|
||||
# make build/extra/gcc-m32/release
|
||||
# # run tests
|
||||
# ./build/extra/gcc-m32/release/upx --version
|
||||
# make -C build/extra/gcc-m32/release test
|
||||
|
||||
# and we can also build UPX with -mx32: (NOTE: needs CONFIG_X86_X32_ABI on host kernel!)
|
||||
# cd /home/upx/src/upx
|
||||
# rm -rf ./build/extra/gcc-mx32/release
|
||||
# make build/extra/gcc-mx32/release
|
||||
# # run tests (needs CONFIG_X86_X32_ABI on host kernel)
|
||||
# ./build/extra/gcc-mx32/release/upx --version
|
||||
# make -C build/extra/gcc-mx32/release test
|
||||
|
||||
# and we can also rebuild the UPX docs the container:
|
||||
# cd /home/upx/src/upx/doc
|
||||
# make clean all
|
||||
# git status .
|
||||
# git diff .
|
||||
@@ -0,0 +1,58 @@
|
||||
FROM docker.io/library/ubuntu:22.04
|
||||
ENV UPX_CONTAINER_IMAGE_NAME=upx-stubtools-20221212-v4
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ENV LANG=C.UTF-8
|
||||
|
||||
# install system packages
|
||||
RUN dpkg --add-architecture i386 \
|
||||
&& apt-get update && apt-get upgrade -y \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
aria2 ca-certificates git less libmpc3 libncurses5 make \
|
||||
ncurses-term perl-base python2-minimal wget xz-utils \
|
||||
libc6:i386 zlib1g:i386 \
|
||||
# the following packages are not required for rebuilding the stubs, but
|
||||
# they do make the image much more convenient and also allow building
|
||||
# the full UPX binary inside the container via CMake:
|
||||
7zip bfs bzip2 cmake curl elfutils fd-find file fzf g++ gdb gojq htop hyperfine \
|
||||
jq libzstd-dev lsb-release lzip lzop ninja-build p7zip patch patchelf pax-utils \
|
||||
ripgrep rsync screen universal-ctags unzip vim zip zlib1g-dev zsh zstd \
|
||||
# extra packages for compiling with "gcc -m32" and and "gcc -mx32":
|
||||
gcc-multilib g++-multilib \
|
||||
&& true
|
||||
|
||||
# manually install compat libs from Ubuntu 16.04; REQUIRED
|
||||
RUN cd /root \
|
||||
&& aria2c --checksum=sha-256=de22baf3dd851a10e16fbf66a243e70149ca46e06b2939fdc79429196cefc090 \
|
||||
'http://archive.kernel.org/ubuntu-archive/ubuntu/pool/main/m/mpfr4/libmpfr4_3.1.6-1_amd64.deb' \
|
||||
&& mkdir packages \
|
||||
&& for f in ./*.deb; do dpkg -x $f ./packages; done \
|
||||
&& mv -v -n ./packages/usr/lib/x86_64-linux-gnu/lib* /usr/lib/x86_64-linux-gnu/ \
|
||||
&& rm -rf ./*.deb ./packages \
|
||||
&& ldconfig \
|
||||
&& true
|
||||
|
||||
# install upx-stubtools into /usr/local/bin/bin-upx-20221212; REQUIRED
|
||||
RUN cd /root \
|
||||
&& aria2c --checksum=sha-256=509e06639118a79d8e79489a400e134c6d3ca36bad2c6ec29648d7c1e5b81afa \
|
||||
'https://github.com/upx/upx-stubtools/releases/download/v20221212/bin-upx-20221212.tar.xz' \
|
||||
&& cd /usr/local/bin \
|
||||
&& tar -xoaf /root/bin-upx-20221212.tar.xz \
|
||||
&& rm /root/bin-upx-20221212.tar.xz \
|
||||
&& true
|
||||
|
||||
# install official UPX release binaries into /usr/local/bin; not required but convenient for testing
|
||||
RUN cd /root \
|
||||
&& wget -q https://github.com/upx/upx/releases/download/v3.91/upx-3.91-amd64_linux.tar.bz2 \
|
||||
&& for v in 3.92 3.93 3.94 3.95 3.96 4.0.0 4.0.1 4.0.2; do wget -q https://github.com/upx/upx/releases/download/v${v}/upx-${v}-amd64_linux.tar.xz; done \
|
||||
&& for f in ./upx-*.tar.*; do tar -xoaf $f; done \
|
||||
&& for v in 3.91 3.92 3.93 3.94 3.95 3.96 4.0.0 4.0.1 4.0.2; do d=upx-${v}-amd64_linux; ./$d/upx -qq -d $d/upx -o /usr/local/bin/upx-${v}; done \
|
||||
&& rm -r ./upx-*.tar.* ./upx-*linux \
|
||||
&& true
|
||||
|
||||
# create default user upx 2000:2000
|
||||
RUN useradd upx -U --uid 2000 --shell /bin/bash -m \
|
||||
&& mkdir -p /home/upx/.cache/zig /home/upx/.local/bin /home/upx/src/upx \
|
||||
&& ln -s /usr/local/bin/bin-upx-20221212 /home/upx/.local/bin/bin-upx \
|
||||
&& chown -R upx:upx /home/upx \
|
||||
&& true
|
||||
USER upx
|
||||
Executable
+39
@@ -0,0 +1,39 @@
|
||||
#! /usr/bin/env bash
|
||||
## vim:set ts=4 sw=4 et:
|
||||
set -e; set -o pipefail
|
||||
|
||||
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
|
||||
|
||||
[[ -z $1 ]] || cd "$1" || exit 1
|
||||
|
||||
find . \
|
||||
-type d -name '.git' -prune -o \
|
||||
-type d -name '.hg' -prune -o \
|
||||
-type d -name 'build*' -prune -o \
|
||||
-type d -name 'tmp*' -prune -o \
|
||||
-type d -name 'vendor' -prune -o \
|
||||
-type f -iname '*.bat' -prune -o \
|
||||
-type f -iname '*.exe' -prune -o \
|
||||
-type f -iname '*.o' -prune -o \
|
||||
-type f -iname '*.obj' -prune -o \
|
||||
-type f -iname '*.out' -prune -o \
|
||||
-type f -iname '*.pdf' -prune -o \
|
||||
-type f -iname '*.swp' -prune -o \
|
||||
-type f -print0 | \
|
||||
LC_ALL=C sort -z | xargs -0r perl -n -e '
|
||||
#print("$ARGV\n");
|
||||
if (m,[\x00\x01\x02\x7f\xfe\xff],) { print "ERROR: binary file detected $ARGV: $_"; exit(1); }
|
||||
if (m,[\r\x1a],) { print "ERROR: DOS EOL detected $ARGV: $_"; exit(1); }
|
||||
if (m,([ \t]+)$,) {
|
||||
# allow exactly two trailing spaces for GitHub flavoured Markdown in .md files
|
||||
if ($1 ne " " || $ARGV !~ m,\.md$,) {
|
||||
print "ERROR: trailing whitespace detected $ARGV: $_"; exit(1);
|
||||
}
|
||||
}
|
||||
if (m,\t,) {
|
||||
if ($ARGV =~ m,(^|/)(gnu|m)?make(file|vars),i) { }
|
||||
elsif ($ARGV =~ m,/tmp/.*\.(disasm|dump)$,) { }
|
||||
elsif ($ARGV =~ m,/src/stub/src/arch/.*/lzma\w+\.S$,) { }
|
||||
else { print "ERROR: hard TAB detected $ARGV: $_"; exit(1); }
|
||||
}
|
||||
' || exit 1
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
#! /usr/bin/env bash
|
||||
## vim:set ts=4 sw=4 et:
|
||||
set -e; set -o pipefail
|
||||
|
||||
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
|
||||
|
||||
[[ -z $1 ]] || cd "$1" || exit 1
|
||||
[[ -d .git ]] || exit 1
|
||||
|
||||
git ls-files --full-name -z | perl -0 -n -e '
|
||||
s,^,./,;
|
||||
if (m,^\./src/lzma-sdk(\0|$),) { }
|
||||
elsif (m,^\./vendor/,) { }
|
||||
elsif (m,\.bat(\0|$),) { }
|
||||
elsif (m,\.exe(\0|$),) { }
|
||||
else { print; }
|
||||
' | LC_ALL=C sort -z | xargs -0r perl -n -e '
|
||||
#print("$ARGV\n");
|
||||
if (m,[\x00\x01\x02\x7f\xfe\xff],) { print "ERROR: binary file detected $ARGV: $_"; exit(1); }
|
||||
if (m,[\r\x1a],) { print "ERROR: DOS EOL detected $ARGV: $_"; exit(1); }
|
||||
if (m,([ \t]+)$,) {
|
||||
# allow exactly two trailing spaces for GitHub flavoured Markdown in .md files
|
||||
if ($1 ne " " || $ARGV !~ m,\.md$,) {
|
||||
print "ERROR: trailing whitespace detected $ARGV: $_"; exit(1);
|
||||
}
|
||||
}
|
||||
if (m,\t,) {
|
||||
if ($ARGV =~ m,(^|/)(gnu|m)?make(file|vars),i) { }
|
||||
elsif ($ARGV =~ m,/tmp/.*\.(disasm|dump)$,) { }
|
||||
elsif ($ARGV =~ m,/src/stub/src/arch/.*/lzma\w+\.S$,) { }
|
||||
else { print "ERROR: hard TAB detected $ARGV: $_"; exit(1); }
|
||||
}
|
||||
' || exit 1
|
||||
Executable
+32
@@ -0,0 +1,32 @@
|
||||
#! /usr/bin/env bash
|
||||
## vim:set ts=4 sw=4 et:
|
||||
set -e; set -o pipefail
|
||||
|
||||
# "Gofmt's style is nobody's favourite, but gofmt is everybody's favourite." --Rob Pike
|
||||
|
||||
# NOTE: we are using clang-format-15.0.6 from upx-stubtools
|
||||
# see https://github.com/upx/upx-stubtools/releases
|
||||
|
||||
# NOTE: we use .clang-format config from upx.git/.clang-format
|
||||
|
||||
if [[ ! -f $UPX_CLANG_FORMAT ]]; then
|
||||
UPX_CLANG_FORMAT="$HOME/local/bin/bin-upx/clang-format-15.0.6"
|
||||
fi
|
||||
if [[ ! -f $UPX_CLANG_FORMAT ]]; then
|
||||
UPX_CLANG_FORMAT="$HOME/.local/bin/bin-upx/clang-format-15.0.6"
|
||||
fi
|
||||
if [[ ! -f $UPX_CLANG_FORMAT ]]; then
|
||||
UPX_CLANG_FORMAT="$HOME/bin/bin-upx/clang-format-15.0.6"
|
||||
fi
|
||||
if [[ ! -f $UPX_CLANG_FORMAT ]]; then
|
||||
echo "ERROR: $0: cannot find clang-format-15.0.6"
|
||||
echo "ERROR: $0: please visit https://github.com/upx/upx-stubtools"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# limit memory usage to 1 GiB (in case of clang-format problems with invalid files)
|
||||
ulimit -v 1048576 || true
|
||||
|
||||
#echo $UPX_CLANG_FORMAT
|
||||
exec "$UPX_CLANG_FORMAT" -style=file "$@"
|
||||
exit 1
|
||||
+82
-87
@@ -1,111 +1,106 @@
|
||||
#
|
||||
# UPX Makefile - needs GNU make 3.81 or better
|
||||
# UPX Makefile - needs GNU make
|
||||
#
|
||||
|
||||
MAKEFLAGS += -rR
|
||||
# IMPORTANT NOTE: this Makefile is deprecated - please
|
||||
# directly use the CMake build instead!
|
||||
|
||||
MAKEFLAGS += -r
|
||||
.SUFFIXES:
|
||||
export SHELL = /bin/sh
|
||||
override e = $($1) $(EXTRA_$1) $(upx_$1) $($(basename $(notdir $@)).$1)
|
||||
|
||||
ifneq ($(findstring $(firstword $(MAKE_VERSION)),3.77 3.78 3.78.1 3.79 3.79.1 3.80),)
|
||||
$(error GNU make 3.81 or better is required)
|
||||
endif
|
||||
|
||||
ifndef srcdir
|
||||
srcdir := $(dir $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)))
|
||||
srcdir := $(shell echo '$(srcdir)' | sed 's,/*$$,,')
|
||||
srcdir := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
srcdir := $(shell echo '$(srcdir)' | sed 's,/*$$,,' || echo 'ERROR')
|
||||
endif
|
||||
ifndef top_srcdir
|
||||
top_srcdir := $(srcdir)/..
|
||||
endif
|
||||
include $(wildcard $(top_srcdir)/Makevars.global ./Makevars.local)
|
||||
ifneq ($(srcdir),.)
|
||||
##$(info Info: using VPATH . $(srcdir))
|
||||
VPATH := . $(srcdir)
|
||||
top_srcdir := $(srcdir)/..
|
||||
endif
|
||||
|
||||
ifeq ($(CXX),)
|
||||
CXX = g++
|
||||
endif
|
||||
ifneq ($(findstring $(firstword $(CXX)),g++),)
|
||||
USE_GNUC ?= 1
|
||||
endif
|
||||
ifeq ($(USE_GNUC),1)
|
||||
ifeq ($(DEBUG),1)
|
||||
CXXFLAGS += -O0 -g
|
||||
else
|
||||
CXXFLAGS += -O2
|
||||
endif
|
||||
CXXFLAGS += -Wall -W -Wcast-align -Wcast-qual -Wpointer-arith -Wwrite-strings -Werror
|
||||
##CXXFLAGS += -Wshadow
|
||||
endif
|
||||
CPPFLAGS += $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES)
|
||||
CXXLD ?= $(CXX)
|
||||
#
|
||||
# redirect to top-level CMake build
|
||||
#
|
||||
|
||||
exeext ?= .out
|
||||
libext ?= .a
|
||||
objext ?= .o
|
||||
.DEFAULT_GOAL = build/debug
|
||||
|
||||
upx_SOURCES := $(wildcard $(srcdir)/*.cpp)
|
||||
upx_OBJECTS := $(notdir $(upx_SOURCES:.cpp=$(objext)))
|
||||
build/debug: $(top_srcdir)/build/debug/upx
|
||||
build/release: $(top_srcdir)/build/release/upx
|
||||
# shortcuts
|
||||
all: build/debug build/release
|
||||
debug: build/debug
|
||||
release: build/release
|
||||
|
||||
# we need UCL and zlib - you can set envvar UPX_UCLDIR
|
||||
ifneq ($(wildcard $(UPX_UCLDIR)/include/ucl/ucl.h),)
|
||||
INCLUDES += -I$(UPX_UCLDIR)/include
|
||||
LIBS += $(addprefix -L,$(dir $(wildcard $(UPX_UCLDIR)/libucl$(libext) $(UPX_UCLDIR)/src/.libs/libucl$(libext))))
|
||||
$(top_srcdir)/build/debug/upx: PHONY
|
||||
$(MAKE) -C $(top_srcdir) build/debug
|
||||
$(top_srcdir)/build/release/upx: PHONY
|
||||
$(MAKE) -C $(top_srcdir) build/release
|
||||
|
||||
.PHONY: PHONY
|
||||
.NOTPARALLEL:
|
||||
|
||||
#
|
||||
# "make run-testsuite"
|
||||
#
|
||||
|
||||
# search for the UPX testsuite -- git clone https://github.com/upx/upx-testsuite.git
|
||||
# you also can override upx_testsuite_SRCDIR
|
||||
ifndef upx_testsuite_SRCDIR
|
||||
# search standard locations below $(top_srcdir)
|
||||
ifneq ($(wildcard $(top_srcdir)/../upx--upx-testsuite.git/files/packed/.),)
|
||||
upx_testsuite_SRCDIR := $(top_srcdir)/../upx--upx-testsuite.git
|
||||
else ifneq ($(wildcard $(top_srcdir)/../upx-testsuite.git/files/packed/.),)
|
||||
upx_testsuite_SRCDIR := $(top_srcdir)/../upx-testsuite.git
|
||||
else ifneq ($(wildcard $(top_srcdir)/../upx-testsuite/files/packed/.),)
|
||||
upx_testsuite_SRCDIR := $(top_srcdir)/../upx-testsuite
|
||||
endif
|
||||
LIBS += -lucl -lz
|
||||
# you should set envvar UPX_LZMADIR to point to your unpacked LZMA SDK
|
||||
include $(top_srcdir)/src/stub/src/c/Makevars.lzma
|
||||
ifneq ($(UPX_LZMA_VERSION),)
|
||||
DEFS += -DWITH_LZMA=$(UPX_LZMA_VERSION)
|
||||
INCLUDES += -I$(UPX_LZMADIR)
|
||||
endif
|
||||
|
||||
|
||||
all: upx$(exeext) | .depend
|
||||
.DELETE_ON_ERROR: upx$(exeext) $(upx_OBJECTS) .depend
|
||||
|
||||
upx$(exeext): $(upx_OBJECTS) $(upx_DEPENDENCIES)
|
||||
$($(notdir $@).PRE_LINK_STEP)
|
||||
$(strip $(CXXLD) $(call e,CPPFLAGS) $(call e,CXXFLAGS) $(call e,LDFLAGS) -o $@ $(upx_OBJECTS) $(call e,LDADD) $(call e,LIBS))
|
||||
$($(notdir $@).POST_LINK_STEP)
|
||||
|
||||
%.o : %.cpp | .depend
|
||||
$(strip $(CXX) $(call e,CPPFLAGS) $(call e,CXXFLAGS) -o $@ -c $<)
|
||||
|
||||
.depend: $(wildcard $(srcdir)/*.cpp $(srcdir)/*.h) $(MAKEFILE_LIST)
|
||||
@rm -f $@
|
||||
ifeq ($(USE_GNUC),1)
|
||||
@echo "Updating $@"
|
||||
@$(strip $(CXX) $(call e,CPPFLAGS) -MM) $(filter %.cpp,$^) > $@
|
||||
else
|
||||
touch $@
|
||||
# run the UPX testsuite
|
||||
# The expected (old) checksums are in $(top_srcdir)/.github/travis_testsuite_1-expected_sha256sums.sh
|
||||
# The actual (new) checksums are in ./tmp-testsuite/testsuite_1/.sha256sums.recreate
|
||||
ifneq ($(wildcard $(upx_testsuite_SRCDIR)/files/packed/.),)
|
||||
ifneq ($(wildcard $(top_srcdir)/.github/travis_testsuite_1.sh),)
|
||||
run-testsuite: run-testsuite-release
|
||||
run-testsuite-%: export upx_testsuite_SRCDIR := $(upx_testsuite_SRCDIR)
|
||||
run-testsuite-%: export upx_testsuite_BUILDDIR := ./tmp-testsuite
|
||||
run-testsuite-debug: export upx_exe := $(top_srcdir)/build/debug/upx
|
||||
run-testsuite-debug: PHONY $(top_srcdir)/build/debug/upx
|
||||
time -p bash $(top_srcdir)/.github/travis_testsuite_1.sh
|
||||
run-testsuite-release: export upx_exe := $(top_srcdir)/build/release/upx
|
||||
run-testsuite-release: PHONY $(top_srcdir)/build/release/upx
|
||||
time -p bash $(top_srcdir)/.github/travis_testsuite_1.sh
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# "make clang-format"
|
||||
#
|
||||
|
||||
ifeq ($(USE_GNUC),1)
|
||||
##compress_lzma$(objext) : CXXFLAGS += -O3 -fomit-frame-pointer
|
||||
compress_lzma$(objext) : CXXFLAGS += -Wno-cast-qual
|
||||
compress_lzma$(objext) : CXXFLAGS += -Wno-shadow
|
||||
ifeq ($(UPX_LZMA_VERSION),0x443)
|
||||
compress_lzma$(objext) : CXXFLAGS += -Wno-non-virtual-dtor
|
||||
compress_lzma$(objext) : CXXFLAGS += -Wno-unused
|
||||
endif
|
||||
# needed for gcc-4.3:
|
||||
compress_lzma$(objext) : CXXFLAGS += -Wno-error
|
||||
# automatically format some C++ source code files
|
||||
ifeq ($(shell uname),Linux)
|
||||
# Markus loves clang-format, but John hates it; find a compromise
|
||||
CLANG_FORMAT_EXCLUDE_FILES += conf.h miniacc.h version.h help.cpp
|
||||
CLANG_FORMAT_EXCLUDE_FILES += p_elf.h p_elf_enum.h p_lx_% p_mach% p_unix% p_vmli%
|
||||
CLANG_FORMAT_EXCLUDE_FILES += packer_c.cpp packer_f.cpp
|
||||
CLANG_FORMAT_EXCLUDE_FILES += compress/compress.h filter/filter_impl.cpp
|
||||
CLANG_FORMAT_FILES := $(sort $(wildcard *.[ch]* ../maint/src/*.[ch]* [cu]*/*.[ch]*))
|
||||
CLANG_FORMAT_FILES := $(filter-out $(CLANG_FORMAT_EXCLUDE_FILES),$(CLANG_FORMAT_FILES))
|
||||
clang-format: PHONY $(CLANG_FORMAT_FILES)
|
||||
@echo "running upx-clang-format"
|
||||
@$(top_srcdir)/misc/scripts/upx-clang-format -i $(CLANG_FORMAT_FILES)
|
||||
endif
|
||||
|
||||
#
|
||||
# "make check-whitespace"
|
||||
#
|
||||
|
||||
mostlyclean clean distclean maintainer-clean:
|
||||
rm -f *.d *.map *.o *.obj *.res .depend upx.exe upx.out upx.ttp upx$(exeext)
|
||||
|
||||
.PHONY: all mostlyclean clean distclean maintainer-clean
|
||||
|
||||
ifeq ($(MAKECMDGOALS),mostlyclean)
|
||||
else ifeq ($(MAKECMDGOALS),clean)
|
||||
else ifeq ($(MAKECMDGOALS),distclean)
|
||||
else ifeq ($(MAKECMDGOALS),maintainer-clean)
|
||||
else
|
||||
-include .depend
|
||||
CHECK_WHITESPACE =
|
||||
ifeq ($(shell uname),Linux)
|
||||
CHECK_WHITESPACE = $(top_srcdir)/misc/scripts/check_whitespace.sh $(top_srcdir)
|
||||
ifneq ($(wildcard $(top_srcdir)/.git/.),)
|
||||
CHECK_WHITESPACE = $(top_srcdir)/misc/scripts/check_whitespace_git.sh $(top_srcdir)
|
||||
endif
|
||||
check-whitespace : PHONY ; $(CHECK_WHITESPACE)
|
||||
endif
|
||||
|
||||
# vim:set ts=8 sw=8 noet:
|
||||
|
||||
+514
-446
File diff suppressed because it is too large
Load Diff
+96
-129
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,56 +22,52 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __UPX_BELE_H
|
||||
# error "this is an internal include file"
|
||||
#ifndef UPX_BELE_H__
|
||||
#error "this is an internal include file"
|
||||
#endif
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
#if defined(BELE_CTP)
|
||||
// CTP - Compile-Time Polymorphism (templates)
|
||||
# define V static inline
|
||||
# define S static int __acc_cdecl_qsort
|
||||
# define C
|
||||
// CTP - Compile-Time Polymorphism (templates)
|
||||
#define V static inline
|
||||
#define S static int __acc_cdecl_qsort
|
||||
#define C /*empty*/
|
||||
#elif defined(BELE_RTP)
|
||||
// RTP - Run-Time Polymorphism (virtual functions)
|
||||
# define V virtual
|
||||
# define S virtual int
|
||||
# define C const
|
||||
// RTP - Run-Time Polymorphism (virtual functions)
|
||||
#define V virtual
|
||||
#define S virtual int
|
||||
#define C const
|
||||
#else
|
||||
# error
|
||||
#error
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(BELE_RTP)
|
||||
struct AbstractPolicy
|
||||
{
|
||||
inline AbstractPolicy() { }
|
||||
virtual inline ~AbstractPolicy() { }
|
||||
struct AbstractPolicy {
|
||||
inline AbstractPolicy() {}
|
||||
virtual inline ~AbstractPolicy() {}
|
||||
V bool isBE() C = 0;
|
||||
V bool isLE() C = 0;
|
||||
|
||||
V unsigned get16(const void *p) C = 0;
|
||||
V unsigned get24(const void *p) C = 0;
|
||||
V unsigned get32(const void *p) C = 0;
|
||||
V acc_uint64l_t get64(const void *p) C = 0;
|
||||
V upx_uint64_t get64(const void *p) C = 0;
|
||||
|
||||
V void set16(void *p, unsigned v) C = 0;
|
||||
V void set24(void *p, unsigned v) C = 0;
|
||||
V void set32(void *p, unsigned v) C = 0;
|
||||
V void set64(void *p, acc_uint64l_t v) C = 0;
|
||||
V void set64(void *p, upx_uint64_t v) C = 0;
|
||||
|
||||
V unsigned get16_signed(const void *p) C = 0;
|
||||
V unsigned get24_signed(const void *p) C = 0;
|
||||
V unsigned get32_signed(const void *p) C = 0;
|
||||
V acc_uint64l_t get64_signed(const void *p) C = 0;
|
||||
V int get16_signed(const void *p) C = 0;
|
||||
V int get24_signed(const void *p) C = 0;
|
||||
V int get32_signed(const void *p) C = 0;
|
||||
V upx_int64_t get64_signed(const void *p) C = 0;
|
||||
|
||||
S u16_compare(const void *a, const void *b) C = 0;
|
||||
S u24_compare(const void *a, const void *b) C = 0;
|
||||
@@ -83,18 +79,27 @@ struct AbstractPolicy
|
||||
S u32_compare_signed(const void *a, const void *b) C = 0;
|
||||
S u64_compare_signed(const void *a, const void *b) C = 0;
|
||||
|
||||
private:
|
||||
// disable copy, assignment and move assignment
|
||||
AbstractPolicy(const AbstractPolicy &) = delete;
|
||||
AbstractPolicy &operator=(const AbstractPolicy &) = delete;
|
||||
AbstractPolicy &operator=(AbstractPolicy &&) = delete;
|
||||
// disable dynamic allocation
|
||||
DISABLE_NEW_DELETE
|
||||
ACC_CXX_DISABLE_NEW_DELETE
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(BELE_RTP)
|
||||
#undef C
|
||||
#define C const override
|
||||
#endif
|
||||
|
||||
struct BEPolicy
|
||||
#if defined(BELE_RTP)
|
||||
: public AbstractPolicy
|
||||
final : public AbstractPolicy
|
||||
#endif
|
||||
{
|
||||
inline BEPolicy() { }
|
||||
inline BEPolicy() {}
|
||||
#if defined(BELE_CTP)
|
||||
typedef N_BELE_RTP::BEPolicy RTP_Policy;
|
||||
#elif defined(BELE_RTP)
|
||||
@@ -107,50 +112,30 @@ struct BEPolicy
|
||||
typedef BE32 U32;
|
||||
typedef BE64 U64;
|
||||
|
||||
V unsigned get16(const void *p) C
|
||||
{ return get_be16(p); }
|
||||
V unsigned get24(const void *p) C
|
||||
{ return get_be24(p); }
|
||||
V unsigned get32(const void *p) C
|
||||
{ return get_be32(p); }
|
||||
V acc_uint64l_t get64(const void *p) C
|
||||
{ return get_be64(p); }
|
||||
V unsigned get16(const void *p) C { return get_be16(p); }
|
||||
V unsigned get24(const void *p) C { return get_be24(p); }
|
||||
V unsigned get32(const void *p) C { return get_be32(p); }
|
||||
V upx_uint64_t get64(const void *p) C { return get_be64(p); }
|
||||
|
||||
V void set16(void *p, unsigned v) C
|
||||
{ set_be16(p, v); }
|
||||
V void set24(void *p, unsigned v) C
|
||||
{ set_be24(p, v); }
|
||||
V void set32(void *p, unsigned v) C
|
||||
{ set_be32(p, v); }
|
||||
V void set64(void *p, acc_uint64l_t v) C
|
||||
{ set_be64(p, v); }
|
||||
V void set16(void *p, unsigned v) C { set_be16(p, v); }
|
||||
V void set24(void *p, unsigned v) C { set_be24(p, v); }
|
||||
V void set32(void *p, unsigned v) C { set_be32(p, v); }
|
||||
V void set64(void *p, upx_uint64_t v) C { set_be64(p, v); }
|
||||
|
||||
V unsigned get16_signed(const void *p) C
|
||||
{ return get_be16_signed(p); }
|
||||
V unsigned get24_signed(const void *p) C
|
||||
{ return get_be24_signed(p); }
|
||||
V unsigned get32_signed(const void *p) C
|
||||
{ return get_be32_signed(p); }
|
||||
V acc_uint64l_t get64_signed(const void *p) C
|
||||
{ return get_be64_signed(p); }
|
||||
V int get16_signed(const void *p) C { return get_be16_signed(p); }
|
||||
V int get24_signed(const void *p) C { return get_be24_signed(p); }
|
||||
V int get32_signed(const void *p) C { return get_be32_signed(p); }
|
||||
V upx_int64_t get64_signed(const void *p) C { return get_be64_signed(p); }
|
||||
|
||||
S u16_compare(const void *a, const void *b) C
|
||||
{ return be16_compare(a, b); }
|
||||
S u24_compare(const void *a, const void *b) C
|
||||
{ return be24_compare(a, b); }
|
||||
S u32_compare(const void *a, const void *b) C
|
||||
{ return be32_compare(a, b); }
|
||||
S u64_compare(const void *a, const void *b) C
|
||||
{ return be64_compare(a, b); }
|
||||
S u16_compare(const void *a, const void *b) C { return be16_compare(a, b); }
|
||||
S u24_compare(const void *a, const void *b) C { return be24_compare(a, b); }
|
||||
S u32_compare(const void *a, const void *b) C { return be32_compare(a, b); }
|
||||
S u64_compare(const void *a, const void *b) C { return be64_compare(a, b); }
|
||||
|
||||
S u16_compare_signed(const void *a, const void *b) C
|
||||
{ return be16_compare_signed(a, b); }
|
||||
S u24_compare_signed(const void *a, const void *b) C
|
||||
{ return be24_compare_signed(a, b); }
|
||||
S u32_compare_signed(const void *a, const void *b) C
|
||||
{ return be32_compare_signed(a, b); }
|
||||
S u64_compare_signed(const void *a, const void *b) C
|
||||
{ return be64_compare_signed(a, b); }
|
||||
S u16_compare_signed(const void *a, const void *b) C { return be16_compare_signed(a, b); }
|
||||
S u24_compare_signed(const void *a, const void *b) C { return be24_compare_signed(a, b); }
|
||||
S u32_compare_signed(const void *a, const void *b) C { return be32_compare_signed(a, b); }
|
||||
S u64_compare_signed(const void *a, const void *b) C { return be64_compare_signed(a, b); }
|
||||
|
||||
static void compileTimeAssertions() {
|
||||
COMPILE_TIME_ASSERT(sizeof(U16) == 2)
|
||||
@@ -161,17 +146,21 @@ struct BEPolicy
|
||||
COMPILE_TIME_ASSERT_ALIGNED1(U64)
|
||||
}
|
||||
|
||||
private:
|
||||
// disable copy, assignment and move assignment
|
||||
BEPolicy(const BEPolicy &) = delete;
|
||||
BEPolicy &operator=(const BEPolicy &) = delete;
|
||||
BEPolicy &operator=(BEPolicy &&) = delete;
|
||||
// disable dynamic allocation
|
||||
DISABLE_NEW_DELETE
|
||||
ACC_CXX_DISABLE_NEW_DELETE
|
||||
};
|
||||
|
||||
|
||||
struct LEPolicy
|
||||
#if defined(BELE_RTP)
|
||||
: public AbstractPolicy
|
||||
final : public AbstractPolicy
|
||||
#endif
|
||||
{
|
||||
inline LEPolicy() { }
|
||||
inline LEPolicy() {}
|
||||
#if defined(BELE_CTP)
|
||||
typedef N_BELE_RTP::LEPolicy RTP_Policy;
|
||||
#elif defined(BELE_RTP)
|
||||
@@ -184,50 +173,30 @@ struct LEPolicy
|
||||
typedef LE32 U32;
|
||||
typedef LE64 U64;
|
||||
|
||||
V unsigned get16(const void *p) C
|
||||
{ return get_le16(p); }
|
||||
V unsigned get24(const void *p) C
|
||||
{ return get_le24(p); }
|
||||
V unsigned get32(const void *p) C
|
||||
{ return get_le32(p); }
|
||||
V acc_uint64l_t get64(const void *p) C
|
||||
{ return get_le64(p); }
|
||||
V unsigned get16(const void *p) C { return get_le16(p); }
|
||||
V unsigned get24(const void *p) C { return get_le24(p); }
|
||||
V unsigned get32(const void *p) C { return get_le32(p); }
|
||||
V upx_uint64_t get64(const void *p) C { return get_le64(p); }
|
||||
|
||||
V void set16(void *p, unsigned v) C
|
||||
{ set_le16(p, v); }
|
||||
V void set24(void *p, unsigned v) C
|
||||
{ set_le24(p, v); }
|
||||
V void set32(void *p, unsigned v) C
|
||||
{ set_le32(p, v); }
|
||||
V void set64(void *p, acc_uint64l_t v) C
|
||||
{ set_le64(p, v); }
|
||||
V void set16(void *p, unsigned v) C { set_le16(p, v); }
|
||||
V void set24(void *p, unsigned v) C { set_le24(p, v); }
|
||||
V void set32(void *p, unsigned v) C { set_le32(p, v); }
|
||||
V void set64(void *p, upx_uint64_t v) C { set_le64(p, v); }
|
||||
|
||||
V unsigned get16_signed(const void *p) C
|
||||
{ return get_le16_signed(p); }
|
||||
V unsigned get24_signed(const void *p) C
|
||||
{ return get_le24_signed(p); }
|
||||
V unsigned get32_signed(const void *p) C
|
||||
{ return get_le32_signed(p); }
|
||||
V acc_uint64l_t get64_signed(const void *p) C
|
||||
{ return get_le64_signed(p); }
|
||||
V int get16_signed(const void *p) C { return get_le16_signed(p); }
|
||||
V int get24_signed(const void *p) C { return get_le24_signed(p); }
|
||||
V int get32_signed(const void *p) C { return get_le32_signed(p); }
|
||||
V upx_int64_t get64_signed(const void *p) C { return get_le64_signed(p); }
|
||||
|
||||
S u16_compare(const void *a, const void *b) C
|
||||
{ return le16_compare(a, b); }
|
||||
S u24_compare(const void *a, const void *b) C
|
||||
{ return le24_compare(a, b); }
|
||||
S u32_compare(const void *a, const void *b) C
|
||||
{ return le32_compare(a, b); }
|
||||
S u64_compare(const void *a, const void *b) C
|
||||
{ return le64_compare(a, b); }
|
||||
S u16_compare(const void *a, const void *b) C { return le16_compare(a, b); }
|
||||
S u24_compare(const void *a, const void *b) C { return le24_compare(a, b); }
|
||||
S u32_compare(const void *a, const void *b) C { return le32_compare(a, b); }
|
||||
S u64_compare(const void *a, const void *b) C { return le64_compare(a, b); }
|
||||
|
||||
S u16_compare_signed(const void *a, const void *b) C
|
||||
{ return le16_compare_signed(a, b); }
|
||||
S u24_compare_signed(const void *a, const void *b) C
|
||||
{ return le24_compare_signed(a, b); }
|
||||
S u32_compare_signed(const void *a, const void *b) C
|
||||
{ return le32_compare_signed(a, b); }
|
||||
S u64_compare_signed(const void *a, const void *b) C
|
||||
{ return le64_compare_signed(a, b); }
|
||||
S u16_compare_signed(const void *a, const void *b) C { return le16_compare_signed(a, b); }
|
||||
S u24_compare_signed(const void *a, const void *b) C { return le24_compare_signed(a, b); }
|
||||
S u32_compare_signed(const void *a, const void *b) C { return le32_compare_signed(a, b); }
|
||||
S u64_compare_signed(const void *a, const void *b) C { return le64_compare_signed(a, b); }
|
||||
|
||||
static void compileTimeAssertions() {
|
||||
COMPILE_TIME_ASSERT(sizeof(U16) == 2)
|
||||
@@ -238,30 +207,33 @@ struct LEPolicy
|
||||
COMPILE_TIME_ASSERT_ALIGNED1(U64)
|
||||
}
|
||||
|
||||
private:
|
||||
// disable copy, assignment and move assignment
|
||||
LEPolicy(const LEPolicy &) = delete;
|
||||
LEPolicy &operator=(const LEPolicy &) = delete;
|
||||
LEPolicy &operator=(LEPolicy &&) = delete;
|
||||
// disable dynamic allocation
|
||||
DISABLE_NEW_DELETE
|
||||
ACC_CXX_DISABLE_NEW_DELETE
|
||||
};
|
||||
|
||||
|
||||
// native policy (aka host policy)
|
||||
#if (ACC_ABI_BIG_ENDIAN)
|
||||
typedef BEPolicy HostPolicy;
|
||||
#elif (ACC_ABI_LITTLE_ENDIAN)
|
||||
typedef LEPolicy HostPolicy;
|
||||
#else
|
||||
# error "ACC_ABI_ENDIAN"
|
||||
#error "ACC_ABI_ENDIAN"
|
||||
#endif
|
||||
|
||||
|
||||
#if 0 /* UNUSED */
|
||||
struct HostAlignedPolicy
|
||||
{
|
||||
struct HostAlignedPolicy {
|
||||
#if defined(BELE_CTP)
|
||||
enum { isBE = HostPolicy::isBE, isLE = HostPolicy::isLE };
|
||||
#endif
|
||||
|
||||
typedef acc_uint16e_t U16;
|
||||
typedef acc_uint32e_t U32;
|
||||
typedef acc_uint64l_t U64;
|
||||
typedef upx_uint16_t U16;
|
||||
typedef upx_uint32_t U32;
|
||||
typedef upx_uint64_t U64;
|
||||
|
||||
static void compileTimeAssertions() {
|
||||
COMPILE_TIME_ASSERT(sizeof(U16) == 2)
|
||||
@@ -271,13 +243,8 @@ struct HostAlignedPolicy
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#undef V
|
||||
#undef S
|
||||
#undef C
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et:nowrap
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
-115
@@ -1,115 +0,0 @@
|
||||
/* bptr.h --
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 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@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __UPX_BPTR_H
|
||||
#define __UPX_BPTR_H
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// BoundedPtr
|
||||
**************************************************************************/
|
||||
|
||||
template <class T>
|
||||
class BoundedPtr
|
||||
{
|
||||
// typedef BoundedPtr<T> Self;
|
||||
public:
|
||||
typedef T* StoredType;
|
||||
typedef T* PointerType;
|
||||
typedef T& ReferenceType;
|
||||
|
||||
~BoundedPtr() { }
|
||||
|
||||
explicit BoundedPtr(void* base, unsigned size, T* ptr=0)
|
||||
: ptr_(ptr), base_(base), size_(size) { check(); }
|
||||
BoundedPtr& operator= (const BoundedPtr& other) {
|
||||
assert(base_ == other.base_); assert(size_ == other.size_);
|
||||
ptr_ = other.ptr_; check(); return *this;
|
||||
}
|
||||
BoundedPtr& operator= (T* other) {
|
||||
ptr_ = other; check(); return *this;
|
||||
}
|
||||
|
||||
operator T* () { check(); return ptr_; }
|
||||
operator const T* () const { check(); return ptr_; }
|
||||
|
||||
BoundedPtr& operator += (size_t n) {
|
||||
checkStrict(); ptr_ += n; checkStrict(); return *this;
|
||||
}
|
||||
BoundedPtr& operator -= (size_t n) {
|
||||
checkStrict(); ptr_ -= n; checkStrict(); return *this;
|
||||
}
|
||||
BoundedPtr& operator ++ (void) {
|
||||
checkStrict(); ptr_ += 1; checkStrict(); return *this;
|
||||
}
|
||||
// T* operator ++ (int) {
|
||||
// T* p = ptr_; checkStrict(); ptr_ += 1; checkStrict(); return p;
|
||||
// }
|
||||
// BoundedPtr& operator -- (void) {
|
||||
// checkStrict(); ptr_ -= 1; checkStrict(); return *this;
|
||||
// }
|
||||
|
||||
|
||||
private:
|
||||
void checkNULL() const {
|
||||
if (!ptr_)
|
||||
throwCantUnpack("unexpected NULL pointer; take care!");
|
||||
}
|
||||
void checkRange(size_t extra=0) const {
|
||||
size_t off = (const char *) ptr_ - (const char *) base_;
|
||||
if (off > size_ || off + extra > size_)
|
||||
throwCantUnpack("pointer out of range; take care!");
|
||||
}
|
||||
void checkStrict(size_t extra=0) const {
|
||||
checkNULL();
|
||||
checkRange(extra);
|
||||
}
|
||||
void check(size_t extra=0) const {
|
||||
if (ptr_) checkRange(extra);
|
||||
}
|
||||
|
||||
T* ptr_;
|
||||
void* base_;
|
||||
size_t size_;
|
||||
|
||||
// disable copy
|
||||
BoundedPtr(const BoundedPtr&); // {}
|
||||
// BoundedPtr& operator= (const BoundedPtr&); // { return *this; }
|
||||
|
||||
// disable dynamic allocation
|
||||
DISABLE_NEW_DELETE
|
||||
};
|
||||
|
||||
|
||||
#endif /* already included */
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,475 @@
|
||||
/* dt_check.cpp -- doctest check
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
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
|
||||
<markus@oberhumer.com>
|
||||
*/
|
||||
|
||||
#include "../conf.h"
|
||||
|
||||
/*************************************************************************
|
||||
// upx_doctest_check()
|
||||
**************************************************************************/
|
||||
|
||||
int upx_doctest_check(int argc, char **argv) {
|
||||
#if defined(DOCTEST_CONFIG_DISABLE)
|
||||
UNUSED(argc);
|
||||
UNUSED(argv);
|
||||
return 0;
|
||||
#else
|
||||
const char *e = getenv("UPX_DEBUG_DOCTEST_DISABLE");
|
||||
if (e && e[0] && strcmp(e, "0") != 0)
|
||||
return 0;
|
||||
bool minimal = true; // only show failing tests
|
||||
bool duration = false; // show timings
|
||||
bool success = false; // show all tests
|
||||
#if DEBUG
|
||||
minimal = false;
|
||||
#endif
|
||||
e = getenv("UPX_DEBUG_DOCTEST_VERBOSE");
|
||||
if (e && e[0]) {
|
||||
minimal = false;
|
||||
if (strcmp(e, "0") == 0) {
|
||||
minimal = true;
|
||||
} else if (strcmp(e, "2") == 0) {
|
||||
duration = true;
|
||||
} else if (strcmp(e, "3") == 0) {
|
||||
duration = true;
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
doctest::Context context;
|
||||
if (minimal)
|
||||
context.setOption("dt-minimal", true);
|
||||
if (duration)
|
||||
context.setOption("dt-duration", true);
|
||||
if (success)
|
||||
context.setOption("dt-success", true);
|
||||
// this requires that main_get_options() understands "--dt-XXX" options
|
||||
if (argc > 0 && argv != nullptr)
|
||||
context.applyCommandLine(argc, argv);
|
||||
int r = context.run();
|
||||
if (r != 0)
|
||||
return 1;
|
||||
if (context.shouldExit())
|
||||
return 2;
|
||||
return 0;
|
||||
#endif // DOCTEST_CONFIG_DISABLE
|
||||
}
|
||||
|
||||
int upx_doctest_check() { return upx_doctest_check(0, nullptr); }
|
||||
|
||||
/*************************************************************************
|
||||
// compile-time checks
|
||||
**************************************************************************/
|
||||
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same<short, upx_int16_t>::value))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same<unsigned short, upx_uint16_t>::value))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same<int, upx_int32_t>::value))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same<unsigned, upx_uint32_t>::value))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same<long long, upx_int64_t>::value))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same<unsigned long long, upx_uint64_t>::value))
|
||||
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(no_bswap16(0x04030201) == 0x0201)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(no_bswap32(0x04030201) == 0x04030201)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(no_bswap64(0x0807060504030201ull) == 0x0807060504030201ull)
|
||||
#if !(ACC_CC_MSC)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(bswap16(0x04030201) == 0x0102)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(bswap32(0x04030201) == 0x01020304)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(bswap64(0x0807060504030201ull) == 0x0102030405060708ull)
|
||||
#endif
|
||||
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_len("") == 0)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_len("a") == 1)
|
||||
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_eq("", ""))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_eq("a", ""))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_eq("", "a"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_eq("abc", "abc"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_eq("ab", "abc"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_eq("abc", "ab"))
|
||||
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_lt("", ""))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_lt("a", ""))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_lt("", "a"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_lt("abc", "abc"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_lt("ab", "abc"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_lt("abc", "ab"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_lt("abc", "aba"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_lt("abc", "abz"))
|
||||
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_ne("abc", "abz"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_gt("abc", "abz"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_ge("abc", "abz"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_le("abc", "abz"))
|
||||
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(CHAR_BIT == 8)
|
||||
#if 0 // does not work with MSVC
|
||||
#if '\0' - 1 < 0
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(CHAR_MAX == 127)
|
||||
#else
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(CHAR_MAX == 255)
|
||||
#endif
|
||||
#if L'\0' - 1 < 0
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((wchar_t) -1 < 0)
|
||||
#else
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((wchar_t) -1 > 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
// upx_compiler_sanity_check()
|
||||
// assert a sane architecture and compiler
|
||||
**************************************************************************/
|
||||
|
||||
namespace {
|
||||
|
||||
template <class T>
|
||||
struct TestBELE {
|
||||
__acc_static_noinline bool test(void) {
|
||||
// POD checks
|
||||
{
|
||||
COMPILE_TIME_ASSERT(std::is_standard_layout<T>::value)
|
||||
COMPILE_TIME_ASSERT(std::is_trivial<T>::value)
|
||||
// extra checks, these are probably implied by std::is_trivial:
|
||||
COMPILE_TIME_ASSERT(std::is_nothrow_default_constructible<T>::value)
|
||||
COMPILE_TIME_ASSERT(std::is_trivially_copyable<T>::value)
|
||||
COMPILE_TIME_ASSERT(std::is_trivially_default_constructible<T>::value)
|
||||
}
|
||||
// alignment checks
|
||||
{
|
||||
COMPILE_TIME_ASSERT_ALIGNED1(T)
|
||||
struct alignas(1) test1_t {
|
||||
char a;
|
||||
T b;
|
||||
};
|
||||
struct alignas(1) test2_t {
|
||||
char a;
|
||||
T b[3];
|
||||
};
|
||||
COMPILE_TIME_ASSERT_ALIGNED1(test1_t)
|
||||
COMPILE_TIME_ASSERT_ALIGNED1(test2_t)
|
||||
test1_t t1[7];
|
||||
test2_t t2[7];
|
||||
COMPILE_TIME_ASSERT(sizeof(test1_t) == 1 + sizeof(T))
|
||||
COMPILE_TIME_ASSERT(sizeof(t1) == 7 + 7 * sizeof(T))
|
||||
COMPILE_TIME_ASSERT(sizeof(test2_t) == 1 + 3 * sizeof(T))
|
||||
COMPILE_TIME_ASSERT(sizeof(t2) == 7 + 21 * sizeof(T))
|
||||
UNUSED(t1);
|
||||
UNUSED(t2);
|
||||
}
|
||||
#if 1
|
||||
// arithmetic checks
|
||||
{
|
||||
T allbits;
|
||||
allbits = 0;
|
||||
allbits += 1;
|
||||
allbits -= 2;
|
||||
T v1;
|
||||
v1 = 1;
|
||||
v1 *= 2;
|
||||
v1 -= 1;
|
||||
T v2;
|
||||
v2 = 1;
|
||||
assert((v1 == v2));
|
||||
assert(!(v1 != v2));
|
||||
assert((v1 <= v2));
|
||||
assert((v1 >= v2));
|
||||
assert(!(v1 < v2));
|
||||
assert(!(v1 > v2));
|
||||
v2 ^= allbits;
|
||||
assert(!(v1 == v2));
|
||||
assert((v1 != v2));
|
||||
assert((v1 <= v2));
|
||||
assert(!(v1 >= v2));
|
||||
assert((v1 < v2));
|
||||
assert(!(v1 > v2));
|
||||
v2 += 2;
|
||||
assert(v1 == 1);
|
||||
assert(v2 == 0);
|
||||
v1 <<= 1;
|
||||
v1 |= v2;
|
||||
v1 >>= 1;
|
||||
v2 &= v1;
|
||||
v2 /= v1;
|
||||
v2 *= v1;
|
||||
assert(v1 == 1);
|
||||
assert(v2 == 0);
|
||||
if ((v1 ^ v2) != 1)
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <class A, class B>
|
||||
struct TestNoAliasingStruct {
|
||||
__acc_static_noinline bool test(A *a, B *b) {
|
||||
*a = 0;
|
||||
*b = 0;
|
||||
*b -= 3;
|
||||
return *a != 0;
|
||||
}
|
||||
};
|
||||
template <class A, class B>
|
||||
__acc_static_forceinline bool testNoAliasing(A *a, B *b) {
|
||||
return TestNoAliasingStruct<A, B>::test(a, b);
|
||||
}
|
||||
template <class T>
|
||||
struct TestIntegerWrap {
|
||||
static inline bool inc(T x) { return x + 1 > x; }
|
||||
static inline bool dec(T x) { return x - 1 < x; }
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#define ACC_WANT_ACC_CHK_CH 1
|
||||
#undef ACCCHK_ASSERT
|
||||
#include "../miniacc.h"
|
||||
|
||||
void upx_compiler_sanity_check(void) {
|
||||
#define ACC_WANT_ACC_CHK_CH 1
|
||||
#undef ACCCHK_ASSERT
|
||||
#define ACCCHK_ASSERT(expr) ACC_COMPILE_TIME_ASSERT(expr)
|
||||
#include "../miniacc.h"
|
||||
#undef ACCCHK_ASSERT
|
||||
|
||||
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(BE16) == 2)
|
||||
COMPILE_TIME_ASSERT(sizeof(BE32) == 4)
|
||||
COMPILE_TIME_ASSERT(sizeof(BE64) == 8)
|
||||
COMPILE_TIME_ASSERT(sizeof(LE16) == 2)
|
||||
COMPILE_TIME_ASSERT(sizeof(LE32) == 4)
|
||||
COMPILE_TIME_ASSERT(sizeof(LE64) == 8)
|
||||
|
||||
COMPILE_TIME_ASSERT_ALIGNED1(BE16)
|
||||
COMPILE_TIME_ASSERT_ALIGNED1(BE32)
|
||||
COMPILE_TIME_ASSERT_ALIGNED1(BE64)
|
||||
COMPILE_TIME_ASSERT_ALIGNED1(LE16)
|
||||
COMPILE_TIME_ASSERT_ALIGNED1(LE32)
|
||||
COMPILE_TIME_ASSERT_ALIGNED1(LE64)
|
||||
|
||||
COMPILE_TIME_ASSERT(sizeof(UPX_VERSION_STRING4) == 4 + 1)
|
||||
assert(strlen(UPX_VERSION_STRING4) == 4);
|
||||
COMPILE_TIME_ASSERT(sizeof(UPX_VERSION_YEAR) == 4 + 1)
|
||||
assert(strlen(UPX_VERSION_YEAR) == 4);
|
||||
assert(memcmp(UPX_VERSION_DATE_ISO, UPX_VERSION_YEAR, 4) == 0);
|
||||
assert(memcmp(&UPX_VERSION_DATE[sizeof(UPX_VERSION_DATE) - 1 - 4], UPX_VERSION_YEAR, 4) == 0);
|
||||
if (gitrev[0]) {
|
||||
size_t revlen = strlen(gitrev);
|
||||
if (strncmp(gitrev, "ERROR", 5) == 0) {
|
||||
assert(revlen == 5 || revlen == 6);
|
||||
} else {
|
||||
assert(revlen == 12 || revlen == 13);
|
||||
}
|
||||
if (revlen == 6 || revlen == 13) {
|
||||
assert(gitrev[revlen - 1] == '+');
|
||||
}
|
||||
}
|
||||
assert(UPX_RSIZE_MAX_MEM == 805306368);
|
||||
|
||||
#if 1
|
||||
assert(TestBELE<LE16>::test());
|
||||
assert(TestBELE<LE32>::test());
|
||||
assert(TestBELE<LE64>::test());
|
||||
assert(TestBELE<BE16>::test());
|
||||
assert(TestBELE<BE32>::test());
|
||||
assert(TestBELE<BE64>::test());
|
||||
{
|
||||
alignas(16) static const unsigned char dd[32] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0,
|
||||
0, 0, 0, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0, 0, 0, 0, 0};
|
||||
const unsigned char *d;
|
||||
const N_BELE_RTP::AbstractPolicy *bele;
|
||||
d = dd + 7;
|
||||
assert(upx_adler32(d, 4) == 0x09f003f7);
|
||||
assert(upx_adler32(d, 4, 0) == 0x09ec03f6);
|
||||
assert(upx_adler32(d, 4, 1) == 0x09f003f7);
|
||||
bele = &N_BELE_RTP::be_policy;
|
||||
assert(get_be16(d) == 0xfffe);
|
||||
assert(bele->get16(d) == 0xfffe);
|
||||
assert(get_be16_signed(d) == -2);
|
||||
assert(get_be24(d) == 0xfffefd);
|
||||
assert(bele->get24(d) == 0xfffefd);
|
||||
assert(get_be24_signed(d) == -259);
|
||||
assert(get_be32(d) == 0xfffefdfc);
|
||||
assert(bele->get32(d) == 0xfffefdfc);
|
||||
assert(get_be32_signed(d) == -66052);
|
||||
bele = &N_BELE_RTP::le_policy;
|
||||
assert(get_le16(d) == 0xfeff);
|
||||
assert(bele->get16(d) == 0xfeff);
|
||||
assert(get_le16_signed(d) == -257);
|
||||
assert(get_le24(d) == 0xfdfeff);
|
||||
assert(bele->get24(d) == 0xfdfeff);
|
||||
assert(get_le24_signed(d) == -131329);
|
||||
assert(get_le32(d) == 0xfcfdfeff);
|
||||
assert(bele->get32(d) == 0xfcfdfeff);
|
||||
assert(get_le32_signed(d) == -50462977);
|
||||
assert(get_le64_signed(d) == -506097522914230529LL);
|
||||
assert(find_be16(d, 2, 0xfffe) == 0);
|
||||
assert(find_le16(d, 2, 0xfeff) == 0);
|
||||
assert(find_be32(d, 4, 0xfffefdfc) == 0);
|
||||
assert(find_le32(d, 4, 0xfcfdfeff) == 0);
|
||||
d += 12;
|
||||
assert(get_be16_signed(d) == 32638);
|
||||
assert(get_be24_signed(d) == 8355453);
|
||||
assert(get_be32_signed(d) == 2138996092);
|
||||
assert(get_be64_signed(d) == 9186918263483431288LL);
|
||||
}
|
||||
{
|
||||
unsigned dd;
|
||||
void *const d = ⅆ
|
||||
dd = ne32_to_le32(0xf7f6f5f4);
|
||||
assert(get_le26(d) == 0x03f6f5f4);
|
||||
set_le26(d, 0);
|
||||
assert(get_le26(d) == 0);
|
||||
assert(dd == ne32_to_le32(0xf4000000));
|
||||
set_le26(d, 0xff020304);
|
||||
assert(get_le26(d) == 0x03020304);
|
||||
assert(dd == ne32_to_le32(0xf7020304));
|
||||
}
|
||||
{
|
||||
upx_uint16_t a;
|
||||
upx_uint32_t b;
|
||||
upx_uint64_t c;
|
||||
set_ne16(&a, 0x04030201); // ignore upper bits
|
||||
set_ne32(&b, 0x04030201);
|
||||
set_ne64(&c, 0x0807060504030201ull);
|
||||
assert(a == 0x0201);
|
||||
assert(b == 0x04030201);
|
||||
assert(c == 0x0807060504030201ull);
|
||||
assert(get_ne16(&a) == 0x0201);
|
||||
assert(get_ne32(&b) == 0x04030201);
|
||||
assert(get_ne64(&c) == 0x0807060504030201ull);
|
||||
}
|
||||
#endif
|
||||
union {
|
||||
short v_short;
|
||||
int v_int;
|
||||
long v_long;
|
||||
long long v_llong;
|
||||
BE16 b16;
|
||||
BE32 b32;
|
||||
BE64 b64;
|
||||
LE16 l16;
|
||||
LE32 l32;
|
||||
LE64 l64;
|
||||
} u;
|
||||
assert(testNoAliasing(&u.v_short, &u.b32));
|
||||
assert(testNoAliasing(&u.v_short, &u.l32));
|
||||
assert(testNoAliasing(&u.v_int, &u.b64));
|
||||
assert(testNoAliasing(&u.v_int, &u.l64));
|
||||
// check working -fno-strict-aliasing
|
||||
assert(testNoAliasing(&u.v_short, &u.v_int));
|
||||
assert(testNoAliasing(&u.v_int, &u.v_long));
|
||||
assert(testNoAliasing(&u.v_int, &u.v_llong));
|
||||
assert(testNoAliasing(&u.v_long, &u.v_llong));
|
||||
|
||||
assert(TestIntegerWrap<unsigned>::inc(0));
|
||||
assert(!TestIntegerWrap<unsigned>::inc(UINT_MAX));
|
||||
assert(TestIntegerWrap<unsigned>::dec(1));
|
||||
assert(!TestIntegerWrap<unsigned>::dec(0));
|
||||
// check working -fno-strict-overflow
|
||||
assert(TestIntegerWrap<int>::inc(0));
|
||||
assert(!TestIntegerWrap<int>::inc(INT_MAX));
|
||||
assert(TestIntegerWrap<int>::dec(0));
|
||||
assert(!TestIntegerWrap<int>::dec(INT_MIN));
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
// some doctest test cases
|
||||
**************************************************************************/
|
||||
|
||||
TEST_CASE("acc_vget") {
|
||||
CHECK_EQ(acc_vget_int(0, 0), 0);
|
||||
CHECK_EQ(acc_vget_long(1, -1), 1);
|
||||
CHECK_EQ(acc_vget_acc_int64l_t(2, 1), 2);
|
||||
CHECK_EQ(acc_vget_acc_hvoid_p(nullptr, 0), nullptr);
|
||||
}
|
||||
|
||||
TEST_CASE("working -fno-strict-aliasing") {
|
||||
bool ok;
|
||||
long v = 0;
|
||||
short *ps = ACC_STATIC_CAST(short *, acc_vget_acc_hvoid_p(&v, 0));
|
||||
int *pi = ACC_STATIC_CAST(int *, acc_vget_acc_hvoid_p(&v, 0));
|
||||
long *pl = ACC_STATIC_CAST(long *, acc_vget_acc_hvoid_p(&v, 0));
|
||||
*ps = 0;
|
||||
*pl = -1;
|
||||
ok = *ps == -1;
|
||||
CHECK(ok);
|
||||
*pi = 0;
|
||||
*pl = -1;
|
||||
ok = *pi == -1;
|
||||
CHECK(ok);
|
||||
*pl = 0;
|
||||
*ps = -1;
|
||||
ok = *pl != 0;
|
||||
CHECK(ok);
|
||||
*pl = 0;
|
||||
*pi = -1;
|
||||
ok = *pl != 0;
|
||||
CHECK(ok);
|
||||
}
|
||||
|
||||
TEST_CASE("working -fno-strict-overflow") {
|
||||
CHECK_EQ(acc_vget_int(INT_MAX, 0) + 1, INT_MIN);
|
||||
CHECK_EQ(acc_vget_int(INT_MIN, 0) - 1, INT_MAX);
|
||||
CHECK_EQ(acc_vget_long(LONG_MAX, 0) + 1, LONG_MIN);
|
||||
CHECK_EQ(acc_vget_long(LONG_MIN, 0) - 1, LONG_MAX);
|
||||
bool ok;
|
||||
int i;
|
||||
i = INT_MAX;
|
||||
i += 1;
|
||||
ok = i == INT_MIN;
|
||||
CHECK(ok);
|
||||
i = INT_MIN;
|
||||
i -= 1;
|
||||
ok = i == INT_MAX;
|
||||
CHECK(ok);
|
||||
}
|
||||
|
||||
TEST_CASE("libc snprintf") {
|
||||
// runtime check that Win32/MinGW <stdio.h> works as expected
|
||||
char buf[64];
|
||||
long long ll = acc_vget_int(-1, 0);
|
||||
unsigned long long llu = (unsigned long long) ll;
|
||||
snprintf(buf, sizeof(buf), "%d.%ld.%lld.%u.%lu.%llu", -3, -2L, ll, 3U, 2LU, llu);
|
||||
CHECK_EQ(strcmp(buf, "-3.-2.-1.3.2.18446744073709551615"), 0);
|
||||
intmax_t im = ll;
|
||||
uintmax_t um = llu;
|
||||
snprintf(buf, sizeof(buf), "%d.%d.%d.%d.%d.%d.%d.%d.%d.%jd", -4, 0, 0, 0, 0, 0, 0, 0, 4, im);
|
||||
CHECK_EQ(strcmp(buf, "-4.0.0.0.0.0.0.0.4.-1"), 0);
|
||||
snprintf(buf, sizeof(buf), "%d.%d.%d.%d.%d.%d.%d.%d.%d.%ju", -5, 0, 0, 0, 0, 0, 0, 0, 5, um);
|
||||
CHECK_EQ(strcmp(buf, "-5.0.0.0.0.0.0.0.5.18446744073709551615"), 0);
|
||||
snprintf(buf, sizeof(buf), "%d.%d.%d.%d.%d.%d.%d.%d.%d.%jx", -6, 0, 0, 0, 0, 0, 0, 0, 6, um);
|
||||
CHECK_EQ(strcmp(buf, "-6.0.0.0.0.0.0.0.6.ffffffffffffffff"), 0);
|
||||
snprintf(buf, sizeof(buf), "%d.%d.%d.%d.%d.%d.%d.%d.%d.%#jx", -7, 0, 0, 0, 0, 0, 0, 0, 7, um);
|
||||
CHECK_EQ(strcmp(buf, "-7.0.0.0.0.0.0.0.7.0xffffffffffffffff"), 0);
|
||||
}
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -0,0 +1,51 @@
|
||||
/* dt_impl.cpp -- doctest support code implementation
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
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
|
||||
<markus@oberhumer.com>
|
||||
*/
|
||||
|
||||
/*************************************************************************
|
||||
// doctest support code implementation
|
||||
**************************************************************************/
|
||||
|
||||
#define DOCTEST_CONFIG_IMPLEMENT
|
||||
#if !defined(UPX_DOCTEST_CONFIG_MULTITHREADING)
|
||||
#define DOCTEST_CONFIG_NO_MULTITHREADING
|
||||
#endif
|
||||
#if defined(__i386__) && defined(__MSDOS__) && defined(__DJGPP__) && defined(__GNUC__)
|
||||
#define DOCTEST_CONFIG_NO_POSIX_SIGNALS
|
||||
#elif defined(__m68k__) && defined(__atarist__) && defined(__GNUC__)
|
||||
#define DOCTEST_CONFIG_COLORS_NONE
|
||||
#define DOCTEST_CONFIG_NO_POSIX_SIGNALS
|
||||
#pragma GCC diagnostic ignored "-Wshadow"
|
||||
#endif
|
||||
#define DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
|
||||
#if !defined(DOCTEST_CONFIG_DISABLE)
|
||||
#if defined(__clang__) && defined(__FAST_MATH__) && defined(__INTEL_LLVM_COMPILER)
|
||||
// warning: comparison with NaN always evaluates to false in fast floating point modes
|
||||
#pragma clang diagnostic ignored "-Wtautological-constant-compare"
|
||||
#endif
|
||||
#include <doctest/doctest/parts/doctest.cpp>
|
||||
#endif
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -0,0 +1,791 @@
|
||||
/* xspan -- a minimally invasive checked memory smart pointer
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
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
|
||||
<markus@oberhumer.com>
|
||||
*/
|
||||
|
||||
// lots of tests (and probably quite a number of redundant tests)
|
||||
|
||||
#include "../conf.h"
|
||||
|
||||
/*************************************************************************
|
||||
// raw_bytes
|
||||
**************************************************************************/
|
||||
|
||||
TEST_CASE("raw_bytes ptr") {
|
||||
upx_uint16_t *ptr = nullptr;
|
||||
CHECK_NOTHROW(raw_bytes(ptr, 0));
|
||||
CHECK_THROWS(raw_bytes(ptr, 1));
|
||||
CHECK_THROWS(raw_index_bytes(ptr, 0, 0));
|
||||
CHECK_THROWS(raw_index_bytes(ptr, 1, 0));
|
||||
CHECK_THROWS(raw_index_bytes(ptr, 0, 1));
|
||||
upx_uint16_t buf[4];
|
||||
ptr = buf;
|
||||
CHECK(ptr_udiff_bytes(raw_index_bytes(ptr, 1, 1), ptr) == 2u);
|
||||
CHECK(ptr_udiff_bytes(raw_index_bytes(ptr, 4, 0), ptr) == 8u);
|
||||
}
|
||||
|
||||
TEST_CASE("raw_bytes bounded array") {
|
||||
upx_uint16_t buf[4];
|
||||
CHECK_NOTHROW(raw_bytes(buf, 8));
|
||||
CHECK_THROWS(raw_bytes(buf, 9));
|
||||
CHECK_NOTHROW(raw_index_bytes(buf, 4, 0));
|
||||
CHECK_THROWS(raw_index_bytes(buf, 4, 1));
|
||||
CHECK_NOTHROW(raw_index_bytes(buf, 3, 2));
|
||||
CHECK_THROWS(raw_index_bytes(buf, 3, 3));
|
||||
CHECK(ptr_udiff_bytes(raw_index_bytes(buf, 1, 1), buf) == 2u);
|
||||
CHECK(ptr_udiff_bytes(raw_index_bytes(buf, 4, 0), buf) == 8u);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
// basic xspan
|
||||
**************************************************************************/
|
||||
|
||||
TEST_CASE("basic xspan usage") {
|
||||
char buf[4] = {0, 1, 2, 3};
|
||||
|
||||
SUBCASE("XSPAN_x") {
|
||||
XSPAN_0(char) a0 = nullptr;
|
||||
|
||||
XSPAN_0(char) b0 = buf;
|
||||
XSPAN_P(char) bp = buf;
|
||||
|
||||
XSPAN_0(char) c0 = XSPAN_0_MAKE(char, buf);
|
||||
XSPAN_P(char) cp = XSPAN_P_MAKE(char, buf);
|
||||
XSPAN_S(char) cs = XSPAN_S_MAKE(char, buf, sizeof(buf));
|
||||
|
||||
XSPAN_0(const char) const x0 = XSPAN_0_MAKE(const char, buf);
|
||||
XSPAN_P(const char) const xp = XSPAN_P_MAKE(const char, buf);
|
||||
XSPAN_S(const char) const xs = XSPAN_S_MAKE(const char, buf, sizeof(buf));
|
||||
XSPAN_P(const char) const yp = xs;
|
||||
XSPAN_0(const char) const z0p = yp;
|
||||
XSPAN_0(const char) const z0s = xs;
|
||||
|
||||
CHECK((a0 == nullptr));
|
||||
CHECK(c0 == b0);
|
||||
CHECK(cp == bp);
|
||||
CHECK(cs == bp);
|
||||
CHECK(x0 == z0p);
|
||||
CHECK(xp == z0s);
|
||||
|
||||
CHECK_NOTHROW(raw_bytes(a0, 0));
|
||||
CHECK_THROWS(raw_bytes(a0, 1));
|
||||
CHECK_THROWS(raw_index_bytes(a0, 0, 0));
|
||||
CHECK(raw_bytes(c0, 4) == buf);
|
||||
CHECK(raw_index_bytes(c0, 1, 3) == buf + 1);
|
||||
CHECK(raw_bytes(cp, 4) == buf);
|
||||
CHECK(raw_index_bytes(cp, 1, 3) == buf + 1);
|
||||
CHECK(raw_bytes(cs, 4) == buf);
|
||||
CHECK(raw_index_bytes(cs, 1, 3) == buf + 1);
|
||||
#if WITH_XSPAN >= 2
|
||||
CHECK_THROWS(raw_bytes(cs, 5));
|
||||
CHECK_THROWS(raw_index_bytes(cs, 1, 4));
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("XSPAN_x_VAR") {
|
||||
XSPAN_0_VAR(char, a0, nullptr);
|
||||
|
||||
XSPAN_0_VAR(char, b0, buf);
|
||||
XSPAN_P_VAR(char, bp, buf);
|
||||
|
||||
XSPAN_0_VAR(char, c0, buf, sizeof(buf));
|
||||
XSPAN_P_VAR(char, cp, buf, sizeof(buf));
|
||||
XSPAN_S_VAR(char, cs, buf, sizeof(buf));
|
||||
|
||||
XSPAN_0_VAR(char, d0, buf + 1, sizeof(buf), buf);
|
||||
XSPAN_P_VAR(char, dp, buf + 1, sizeof(buf), buf);
|
||||
XSPAN_S_VAR(char, ds, buf + 1, sizeof(buf), buf);
|
||||
|
||||
XSPAN_0_VAR(const char, const x0, buf, sizeof(buf));
|
||||
XSPAN_P_VAR(const char, const xp, buf, sizeof(buf));
|
||||
XSPAN_S_VAR(const char, const xs, buf, sizeof(buf));
|
||||
XSPAN_P_VAR(const char, const yp, xs);
|
||||
XSPAN_0_VAR(const char, const z0p, yp);
|
||||
XSPAN_0_VAR(const char, const z0s, xs);
|
||||
|
||||
CHECK((a0 == nullptr));
|
||||
CHECK(c0 == b0);
|
||||
CHECK(cp == bp);
|
||||
CHECK(cs == bp);
|
||||
CHECK(d0 == dp);
|
||||
CHECK(d0 == ds);
|
||||
CHECK(x0 == z0p);
|
||||
CHECK(xp == z0s);
|
||||
|
||||
CHECK_NOTHROW(raw_bytes(a0, 0));
|
||||
CHECK_THROWS(raw_bytes(a0, 1));
|
||||
CHECK_THROWS(raw_index_bytes(a0, 0, 0));
|
||||
CHECK(raw_bytes(c0, 4) == buf);
|
||||
CHECK(raw_index_bytes(c0, 1, 3) == buf + 1);
|
||||
CHECK(raw_bytes(cp, 4) == buf);
|
||||
CHECK(raw_index_bytes(cp, 1, 3) == buf + 1);
|
||||
CHECK(raw_bytes(cs, 4) == buf);
|
||||
CHECK(raw_index_bytes(cs, 1, 3) == buf + 1);
|
||||
#if WITH_XSPAN >= 2
|
||||
CHECK_THROWS(raw_bytes(cs, 5));
|
||||
CHECK_THROWS(raw_index_bytes(cs, 1, 4));
|
||||
#endif
|
||||
}
|
||||
|
||||
SUBCASE("xspan in class") {
|
||||
struct MyType {
|
||||
XSPAN_0(char) s0;
|
||||
XSPAN_P(char) sp;
|
||||
XSPAN_S(char) ss;
|
||||
#if __cplusplus >= 201103L
|
||||
XSPAN_0(char) x0 = nullptr;
|
||||
#endif
|
||||
#if WITH_XSPAN >= 2
|
||||
// much nicer syntax when using fully checked xspan:
|
||||
MyType(char *b, size_t n, bool) : s0(b, n), sp(b, n), ss(b, n) {}
|
||||
#endif
|
||||
MyType(char *b, size_t n)
|
||||
: s0(XSPAN_0_MAKE(char, b, n)), sp(XSPAN_P_MAKE(char, b, n)),
|
||||
ss(XSPAN_S_MAKE(char, b, n)) {
|
||||
UNUSED(n);
|
||||
}
|
||||
};
|
||||
MyType x(buf, sizeof(buf));
|
||||
MyType y = MyType(buf, sizeof(buf));
|
||||
CHECK(x.s0 == y.sp);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
#if (WITH_XSPAN >= 2) && DEBUG
|
||||
|
||||
TEST_CASE("PtrOrSpanOrNull") {
|
||||
char real_buf[2 + 6 + 2] = {126, 127, 0, 1, 2, 3, 4, 5, 124, 125};
|
||||
char *base_buf = real_buf + 2;
|
||||
char *const my_null = nullptr;
|
||||
typedef PtrOrSpanOrNull<char> Span0;
|
||||
|
||||
// basic nullptr
|
||||
CHECK_NOTHROW(Span0(base_buf, 4, base_buf) = my_null);
|
||||
CHECK_NOTHROW(Span0(base_buf, 4, base_buf).assign(my_null));
|
||||
// basic range checking
|
||||
CHECK_NOTHROW(Span0(base_buf, 4, base_buf));
|
||||
CHECK_NOTHROW(Span0(base_buf, 0, base_buf));
|
||||
CHECK_NOTHROW(Span0(base_buf, 0, base_buf) - 0);
|
||||
CHECK_THROWS(Span0(base_buf, 0, base_buf) + 1);
|
||||
CHECK_THROWS(Span0(base_buf, 0, base_buf) - 1);
|
||||
CHECK_NOTHROW(Span0(base_buf, 4, base_buf) + 4);
|
||||
CHECK_THROWS(Span0(base_buf, 4, base_buf) + 5);
|
||||
CHECK_THROWS(Span0(base_buf - 1, 4, base_buf));
|
||||
CHECK_THROWS(Span0(base_buf + 1, 0, base_buf));
|
||||
// basic same base
|
||||
CHECK_NOTHROW(Span0(base_buf, 4, base_buf) = Span0(base_buf + 1, 3, base_buf));
|
||||
CHECK_NOTHROW(Span0(base_buf, 4, base_buf) = Span0(base_buf + 1, 1, base_buf));
|
||||
CHECK_NOTHROW(Span0(base_buf, 4, base_buf) = Span0(base_buf + 1, 5, base_buf));
|
||||
CHECK_THROWS(Span0(base_buf, 4, base_buf) = Span0(base_buf + 1, 3, base_buf + 1));
|
||||
|
||||
Span0 a1(nullptr);
|
||||
assert(a1 == nullptr);
|
||||
assert(a1.raw_ptr() == nullptr);
|
||||
assert(a1.raw_base() == nullptr);
|
||||
assert(a1.raw_size_in_bytes() == 0u);
|
||||
CHECK_THROWS(*a1);
|
||||
CHECK_THROWS(a1[0]);
|
||||
|
||||
Span0 a2 = nullptr;
|
||||
assert(a2 == nullptr);
|
||||
assert(a2.raw_ptr() == nullptr);
|
||||
assert(a2.raw_base() == nullptr);
|
||||
assert(a2.raw_size_in_bytes() == 0u);
|
||||
CHECK_THROWS(*a2);
|
||||
CHECK_THROWS(a2[0]);
|
||||
|
||||
Span0 base0(nullptr, 4, base_buf);
|
||||
assert(base0.raw_ptr() == nullptr);
|
||||
assert(base0.raw_base() == base_buf);
|
||||
assert(base0.raw_size_in_bytes() == 4u);
|
||||
CHECK_THROWS(*base0); // nullptr
|
||||
CHECK_THROWS(base0[0]); // nullptr
|
||||
CHECK_THROWS(base0 + 1); // nullptr
|
||||
|
||||
Span0 base4(base_buf, 4);
|
||||
assert(base4.raw_ptr() == base_buf);
|
||||
assert(base4.raw_base() == base_buf);
|
||||
assert(base4.raw_size_in_bytes() == 4u);
|
||||
|
||||
a1 = base_buf;
|
||||
a1 = base0;
|
||||
assert(a1 == nullptr);
|
||||
assert(a1.raw_ptr() == nullptr);
|
||||
assert(a1.raw_base() == base_buf);
|
||||
assert(a1.raw_size_in_bytes() == 4u);
|
||||
a1 = base4;
|
||||
assert(a1 == base_buf);
|
||||
assert(a1.raw_ptr() == base_buf);
|
||||
assert(a1.raw_base() == base_buf);
|
||||
assert(a1.raw_size_in_bytes() == 4u);
|
||||
|
||||
a1 = base_buf;
|
||||
assert(a1 != nullptr);
|
||||
a1 = base_buf + 1;
|
||||
CHECK(*a1++ == 1);
|
||||
CHECK(*++a1 == 3);
|
||||
CHECK(*a1 == 3);
|
||||
a1 = base_buf + 4; // at the end of buffer
|
||||
CHECK_THROWS(*a1);
|
||||
CHECK_THROWS(a1 = base_buf + 5); // range error
|
||||
assert(a1 == base_buf + 4);
|
||||
CHECK(a1[-4] == 0);
|
||||
CHECK_THROWS(a1[-5]); // range error
|
||||
a1 = base_buf;
|
||||
CHECK(*a1 == 0);
|
||||
|
||||
Span0 new_base4(base_buf + 2, 4);
|
||||
CHECK_THROWS(a1 = new_base4); // not same base
|
||||
a2 = new_base4;
|
||||
CHECK_THROWS(a2 = base4); // not same base
|
||||
|
||||
Span0 s0_no_base(nullptr);
|
||||
Span0 s0_with_base(nullptr, 4, base_buf);
|
||||
s0_no_base = nullptr;
|
||||
s0_with_base = nullptr;
|
||||
s0_with_base = s0_no_base;
|
||||
assert(s0_no_base.raw_base() == nullptr);
|
||||
assert(s0_with_base.raw_base() == base_buf);
|
||||
s0_no_base = s0_with_base;
|
||||
assert(s0_no_base.raw_base() == base_buf);
|
||||
assert(s0_no_base.raw_ptr() == nullptr);
|
||||
assert(s0_with_base.raw_ptr() == nullptr);
|
||||
s0_no_base = my_null;
|
||||
s0_with_base = my_null;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
TEST_CASE("PtrOrSpan") {
|
||||
char real_buf[2 + 6 + 2] = {126, 127, 0, 1, 2, 3, 4, 5, 124, 125};
|
||||
char *base_buf = real_buf + 2;
|
||||
char *const my_null = nullptr;
|
||||
typedef PtrOrSpan<char> SpanP;
|
||||
|
||||
// basic nullptr
|
||||
CHECK_THROWS(SpanP(base_buf, 4, base_buf) = my_null);
|
||||
CHECK_THROWS(SpanP(base_buf, 4, base_buf).assign(my_null));
|
||||
// basic range checking
|
||||
CHECK_NOTHROW(SpanP(base_buf, 4, base_buf));
|
||||
CHECK_NOTHROW(SpanP(base_buf, 0, base_buf));
|
||||
CHECK_NOTHROW(SpanP(base_buf, 0, base_buf) - 0);
|
||||
CHECK_THROWS(SpanP(base_buf, 0, base_buf) + 1);
|
||||
CHECK_THROWS(SpanP(base_buf, 0, base_buf) - 1);
|
||||
CHECK_NOTHROW(SpanP(base_buf, 4, base_buf) + 4);
|
||||
CHECK_THROWS(SpanP(base_buf, 4, base_buf) + 5);
|
||||
CHECK_THROWS(SpanP(base_buf - 1, 4, base_buf));
|
||||
CHECK_THROWS(SpanP(base_buf + 1, 0, base_buf));
|
||||
// basic same base
|
||||
CHECK_NOTHROW(SpanP(base_buf, 4, base_buf) = SpanP(base_buf + 1, 3, base_buf));
|
||||
CHECK_NOTHROW(SpanP(base_buf, 4, base_buf) = SpanP(base_buf + 1, 1, base_buf));
|
||||
CHECK_NOTHROW(SpanP(base_buf, 4, base_buf) = SpanP(base_buf + 1, 5, base_buf));
|
||||
CHECK_THROWS(SpanP(base_buf, 4, base_buf) = SpanP(base_buf + 1, 3, base_buf + 1));
|
||||
|
||||
SpanP x1(base_buf, 0);
|
||||
assert(x1 != nullptr);
|
||||
assert(x1.raw_ptr() == base_buf);
|
||||
assert(x1.raw_base() == base_buf);
|
||||
assert(x1.raw_size_in_bytes() == 0u);
|
||||
CHECK_THROWS(*x1);
|
||||
CHECK_THROWS(x1[0]);
|
||||
|
||||
SpanP a2 = base_buf;
|
||||
assert(a2 != nullptr);
|
||||
assert(a2.raw_ptr() == base_buf);
|
||||
assert(a2.raw_base() == nullptr);
|
||||
assert(a2.raw_size_in_bytes() == 0u);
|
||||
CHECK(*a2 == 0);
|
||||
CHECK(a2[1] == 1);
|
||||
|
||||
SpanP base0(base_buf, 4, base_buf);
|
||||
assert(base0.raw_ptr() == base_buf);
|
||||
assert(base0.raw_base() == base_buf);
|
||||
assert(base0.raw_size_in_bytes() == 4u);
|
||||
|
||||
SpanP base4(base_buf, 4);
|
||||
assert(base4.raw_ptr() == base_buf);
|
||||
assert(base4.raw_base() == base_buf);
|
||||
assert(base4.raw_size_in_bytes() == 4u);
|
||||
|
||||
SpanP a1(base_buf, 4);
|
||||
a1 = base_buf;
|
||||
a1 = base0;
|
||||
assert(a1 == base0);
|
||||
assert(a1 != nullptr);
|
||||
assert(a1.raw_ptr() == base0.raw_ptr());
|
||||
assert(a1.raw_base() == base_buf);
|
||||
assert(a1.raw_size_in_bytes() == 4u);
|
||||
a1 = base4;
|
||||
assert(a1 == base_buf);
|
||||
assert(a1.raw_ptr() == base_buf);
|
||||
assert(a1.raw_base() == base_buf);
|
||||
assert(a1.raw_size_in_bytes() == 4u);
|
||||
|
||||
a1 = base_buf;
|
||||
a1 = base_buf + 1;
|
||||
CHECK(*a1++ == 1);
|
||||
CHECK(*++a1 == 3);
|
||||
CHECK(*a1 == 3);
|
||||
a1 = base_buf + 4; // at the end of buffer
|
||||
CHECK_THROWS(*a1);
|
||||
CHECK_THROWS(a1 = base_buf + 5); // range error
|
||||
assert(a1 == base_buf + 4);
|
||||
CHECK(a1[-4] == 0);
|
||||
CHECK_THROWS(a1[-5]); // range error
|
||||
a1 = base_buf;
|
||||
CHECK(*a1 == 0);
|
||||
|
||||
SpanP new_base4(base_buf + 2, 4);
|
||||
CHECK_THROWS(a1 = new_base4); // not same base
|
||||
a2 = new_base4;
|
||||
CHECK_THROWS(a2 = base4); // not same base
|
||||
|
||||
SpanP sp_no_base(base_buf);
|
||||
SpanP sp_with_base(base_buf, 4, base_buf);
|
||||
assert(sp_no_base.raw_base() == nullptr);
|
||||
assert(sp_with_base.raw_base() == base_buf);
|
||||
CHECK_THROWS(sp_no_base = my_null); // nullptr assignment
|
||||
CHECK_THROWS(sp_with_base = my_null); // nullptr assignment
|
||||
#if XSPAN_CONFIG_ENABLE_SPAN_CONVERSION
|
||||
typedef PtrOrSpanOrNull<char> Span0;
|
||||
Span0 s0_no_base(nullptr);
|
||||
Span0 s0_with_base(nullptr, 4, base_buf);
|
||||
CHECK_THROWS(sp_no_base = s0_no_base); // nullptr assignment
|
||||
CHECK_THROWS(sp_no_base = s0_with_base); // nullptr assignment
|
||||
CHECK_THROWS(sp_with_base = s0_no_base); // nullptr assignment
|
||||
CHECK_THROWS(sp_with_base = s0_with_base); // nullptr assignment
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
TEST_CASE("Span") {
|
||||
char real_buf[2 + 6 + 2] = {126, 127, 0, 1, 2, 3, 4, 5, 124, 125};
|
||||
char *base_buf = real_buf + 2;
|
||||
char *const my_null = nullptr;
|
||||
typedef Span<char> SpanS;
|
||||
|
||||
// basic nullptr
|
||||
CHECK_THROWS(SpanS(base_buf, 4, base_buf) = my_null);
|
||||
CHECK_THROWS(SpanS(base_buf, 4, base_buf).assign(my_null));
|
||||
// basic range checking
|
||||
CHECK_NOTHROW(SpanS(base_buf, 4, base_buf));
|
||||
CHECK_NOTHROW(SpanS(base_buf, 0, base_buf));
|
||||
CHECK_NOTHROW(SpanS(base_buf, 0, base_buf) - 0);
|
||||
CHECK_THROWS(SpanS(base_buf, 0, base_buf) + 1);
|
||||
CHECK_THROWS(SpanS(base_buf, 0, base_buf) - 1);
|
||||
CHECK_NOTHROW(SpanS(base_buf, 4, base_buf) + 4);
|
||||
CHECK_THROWS(SpanS(base_buf, 4, base_buf) + 5);
|
||||
CHECK_THROWS(SpanS(base_buf - 1, 4, base_buf));
|
||||
CHECK_THROWS(SpanS(base_buf + 1, 0, base_buf));
|
||||
// basic same base
|
||||
CHECK_NOTHROW(SpanS(base_buf, 4, base_buf) = SpanS(base_buf + 1, 3, base_buf));
|
||||
CHECK_NOTHROW(SpanS(base_buf, 4, base_buf) = SpanS(base_buf + 1, 1, base_buf));
|
||||
CHECK_NOTHROW(SpanS(base_buf, 4, base_buf) = SpanS(base_buf + 1, 5, base_buf));
|
||||
CHECK_THROWS(SpanS(base_buf, 4, base_buf) = SpanS(base_buf + 1, 3, base_buf + 1));
|
||||
|
||||
SpanS x1(base_buf, 0);
|
||||
assert(x1 != nullptr);
|
||||
assert(x1.raw_ptr() == base_buf);
|
||||
assert(x1.raw_base() == base_buf);
|
||||
assert(x1.raw_size_in_bytes() == 0u);
|
||||
CHECK_THROWS(*x1);
|
||||
CHECK_THROWS(x1[0]);
|
||||
|
||||
SpanS a2(base_buf, 4);
|
||||
assert(a2 != nullptr);
|
||||
assert(a2.raw_ptr() == base_buf);
|
||||
assert(a2.raw_base() == base_buf);
|
||||
assert(a2.raw_size_in_bytes() == 4u);
|
||||
CHECK(*a2 == 0);
|
||||
CHECK(a2[1] == 1);
|
||||
|
||||
SpanS base0(base_buf, 4, base_buf);
|
||||
assert(base0.raw_ptr() == base_buf);
|
||||
assert(base0.raw_base() == base_buf);
|
||||
assert(base0.raw_size_in_bytes() == 4u);
|
||||
|
||||
SpanS base4(base_buf, 4);
|
||||
assert(base4.raw_ptr() == base_buf);
|
||||
assert(base4.raw_base() == base_buf);
|
||||
assert(base4.raw_size_in_bytes() == 4u);
|
||||
|
||||
SpanS a1(base_buf, 4);
|
||||
a1 = base_buf;
|
||||
a1 = base0;
|
||||
assert(a1 == base0);
|
||||
assert(a1 != nullptr);
|
||||
assert(a1.raw_ptr() == base0.raw_ptr());
|
||||
assert(a1.raw_base() == base_buf);
|
||||
assert(a1.raw_size_in_bytes() == 4u);
|
||||
a1 = base4;
|
||||
assert(a1 == base_buf);
|
||||
assert(a1.raw_ptr() == base_buf);
|
||||
assert(a1.raw_base() == base_buf);
|
||||
assert(a1.raw_size_in_bytes() == 4u);
|
||||
|
||||
a1 = base_buf;
|
||||
a1 = base_buf + 1;
|
||||
CHECK(*a1++ == 1);
|
||||
CHECK(*++a1 == 3);
|
||||
CHECK(*a1 == 3);
|
||||
a1 = base_buf + 4; // at the end of buffer
|
||||
CHECK_THROWS(*a1);
|
||||
CHECK_THROWS(a1 = base_buf + 5); // range error
|
||||
assert(a1 == base_buf + 4);
|
||||
CHECK(a1[-4] == 0);
|
||||
CHECK_THROWS(a1[-5]); // range error
|
||||
a1 = base_buf;
|
||||
CHECK(*a1 == 0);
|
||||
|
||||
SpanS new_base4(base_buf + 2, 4);
|
||||
CHECK_THROWS(a1 = new_base4); // not same base
|
||||
CHECK_THROWS(a2 = new_base4); // not same base
|
||||
|
||||
SpanS ss_with_base(base_buf, 4, base_buf);
|
||||
assert(ss_with_base.raw_base() == base_buf);
|
||||
CHECK_THROWS(ss_with_base = my_null); // nullptr assignment
|
||||
#if XSPAN_CONFIG_ENABLE_SPAN_CONVERSION
|
||||
{
|
||||
typedef PtrOrSpanOrNull<char> Span0;
|
||||
// v0 nullptr, b0 base, b1 base + 1
|
||||
const Span0 v0_v0(nullptr);
|
||||
const Span0 v0_b0(nullptr, 4, base_buf);
|
||||
const Span0 v0_b1(nullptr, 3, base_buf + 1);
|
||||
const Span0 b0_v0(base_buf);
|
||||
const Span0 b0_b0(base_buf, 4, base_buf);
|
||||
CHECK_THROWS(XSPAN_0_MAKE(char, base_buf, 3, base_buf + 1)); // b0_b1
|
||||
const Span0 b1_v0(base_buf + 1);
|
||||
const Span0 b1_b0(base_buf + 1, 4, base_buf);
|
||||
const Span0 b1_b1(base_buf + 1, 3, base_buf + 1);
|
||||
CHECK_THROWS(ss_with_base = v0_v0); // nullptr assignment
|
||||
CHECK_THROWS(ss_with_base = v0_b0); // nullptr assignment
|
||||
CHECK_THROWS(ss_with_base = v0_b1); // nullptr assignment
|
||||
CHECK_NOTHROW(ss_with_base = b0_v0);
|
||||
CHECK_NOTHROW(ss_with_base = b0_b0);
|
||||
CHECK_NOTHROW(ss_with_base = b1_v0);
|
||||
CHECK_NOTHROW(ss_with_base = b1_b0);
|
||||
CHECK_THROWS(ss_with_base = b1_b1); // different base
|
||||
CHECK_THROWS(XSPAN_S_MAKE(char, v0_v0));
|
||||
CHECK_THROWS(XSPAN_S_MAKE(char, v0_b0));
|
||||
CHECK_THROWS(XSPAN_S_MAKE(char, v0_b1));
|
||||
CHECK_THROWS(XSPAN_S_MAKE(char, b0_v0));
|
||||
CHECK_NOTHROW(XSPAN_S_MAKE(char, b0_b0));
|
||||
CHECK_THROWS(XSPAN_S_MAKE(char, b1_v0));
|
||||
CHECK_NOTHROW(XSPAN_S_MAKE(char, b1_b0));
|
||||
CHECK_NOTHROW(XSPAN_S_MAKE(char, b1_b1));
|
||||
//
|
||||
CHECK((XSPAN_S_MAKE(char, b0_b0).raw_base() == base_buf));
|
||||
CHECK((XSPAN_S_MAKE(char, b1_b0).raw_base() == base_buf));
|
||||
CHECK((XSPAN_S_MAKE(char, b1_b1).raw_base() == base_buf + 1));
|
||||
}
|
||||
{
|
||||
typedef PtrOrSpan<char> SpanP;
|
||||
// v0 nullptr, b0 base, b1 base + 1
|
||||
const SpanP b0_v0(base_buf);
|
||||
const SpanP b0_b0(base_buf, 4, base_buf);
|
||||
CHECK_THROWS(XSPAN_P_MAKE(char, base_buf, 3, base_buf + 1)); // b0_b1
|
||||
const SpanP b1_v0(base_buf + 1);
|
||||
const SpanP b1_b0(base_buf + 1, 4, base_buf);
|
||||
const SpanP b1_b1(base_buf + 1, 3, base_buf + 1);
|
||||
CHECK_NOTHROW(ss_with_base = b0_v0);
|
||||
CHECK_NOTHROW(ss_with_base = b0_b0);
|
||||
CHECK_NOTHROW(ss_with_base = b1_v0);
|
||||
CHECK_NOTHROW(ss_with_base = b1_b0);
|
||||
CHECK_THROWS(ss_with_base = b1_b1); // different base
|
||||
CHECK_THROWS(XSPAN_S_MAKE(char, b0_v0));
|
||||
CHECK_NOTHROW(XSPAN_S_MAKE(char, b0_b0));
|
||||
CHECK_THROWS(XSPAN_S_MAKE(char, b1_v0));
|
||||
CHECK_NOTHROW(XSPAN_S_MAKE(char, b1_b0));
|
||||
CHECK_NOTHROW(XSPAN_S_MAKE(char, b1_b1));
|
||||
//
|
||||
CHECK((XSPAN_S_MAKE(char, b0_b0).raw_base() == base_buf));
|
||||
CHECK((XSPAN_S_MAKE(char, b1_b0).raw_base() == base_buf));
|
||||
CHECK((XSPAN_S_MAKE(char, b1_b1).raw_base() == base_buf + 1));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
TEST_CASE("Span void ptr") {
|
||||
static char a[4] = {0, 1, 2, 3};
|
||||
XSPAN_0(void) a0(a, 4);
|
||||
XSPAN_P(void) ap(a, 4);
|
||||
XSPAN_S(void) as(a, 4);
|
||||
XSPAN_0(const void) c0(a, 4);
|
||||
XSPAN_P(const void) cp(a, 4);
|
||||
XSPAN_S(const void) cs(a, 4);
|
||||
static const char b[4] = {0, 1, 2, 3};
|
||||
XSPAN_0(const void) b0(b, 4);
|
||||
XSPAN_P(const void) bp(b, 4);
|
||||
XSPAN_S(const void) bs(b, 4);
|
||||
}
|
||||
|
||||
TEST_CASE("Span deref/array/arrow") {
|
||||
static char real_a[2 + 4 + 2] = {126, 127, 0, 1, 2, 3, 124, 125};
|
||||
static char *a = real_a + 2;
|
||||
XSPAN_0(char) a0(a, 4);
|
||||
XSPAN_P(char) ap(a, 4);
|
||||
XSPAN_S(char) as(a, 4);
|
||||
CHECK_THROWS(a0[4]);
|
||||
CHECK_THROWS(a0[-1]);
|
||||
CHECK_THROWS(a0[-2]);
|
||||
a0 += 2;
|
||||
CHECK(*a0 == 2);
|
||||
CHECK(a0[-1] == 1);
|
||||
CHECK(a0[0] == 2);
|
||||
CHECK(a0[1] == 3);
|
||||
ap += 2;
|
||||
CHECK(*ap == 2);
|
||||
CHECK(ap[-1] == 1);
|
||||
CHECK(ap[0] == 2);
|
||||
CHECK(ap[1] == 3);
|
||||
as += 2;
|
||||
CHECK(*as == 2);
|
||||
CHECK(as[-1] == 1);
|
||||
CHECK(as[0] == 2);
|
||||
CHECK(as[1] == 3);
|
||||
}
|
||||
|
||||
TEST_CASE("Span subspan") {
|
||||
static char buf[4] = {0, 1, 2, 3};
|
||||
XSPAN_S(char) as(buf, 4);
|
||||
CHECK(as.subspan(1, 1)[0] == 1);
|
||||
CHECK((as + 1).subspan(1, 1)[0] == 2);
|
||||
CHECK((as + 2).subspan(0, -2)[0] == 0);
|
||||
CHECK_THROWS(as.subspan(1, 0)[0]);
|
||||
CHECK_THROWS(as.subspan(1, 1)[-1]);
|
||||
}
|
||||
|
||||
TEST_CASE("Span constness") {
|
||||
static char buf[4] = {0, 1, 2, 3};
|
||||
|
||||
XSPAN_0(char) b0(buf, 4);
|
||||
XSPAN_P(char) bp(buf, 4);
|
||||
XSPAN_S(char) bs(buf, 4);
|
||||
|
||||
XSPAN_0(char) s0(b0);
|
||||
XSPAN_P(char) sp(bp);
|
||||
XSPAN_S(char) ss(bs);
|
||||
|
||||
XSPAN_0(const char) b0c(buf, 4);
|
||||
XSPAN_P(const char) bpc(buf, 4);
|
||||
XSPAN_S(const char) bsc(buf, 4);
|
||||
|
||||
XSPAN_0(const char) s0c(b0c);
|
||||
XSPAN_P(const char) spc(bpc);
|
||||
XSPAN_S(const char) ssc(bsc);
|
||||
|
||||
XSPAN_0(const char) x0c(b0);
|
||||
XSPAN_P(const char) xpc(bp);
|
||||
XSPAN_S(const char) xsc(bs);
|
||||
|
||||
CHECK(ptr_diff_bytes(b0, buf) == 0);
|
||||
CHECK(ptr_diff_bytes(bp, buf) == 0);
|
||||
CHECK(ptr_diff_bytes(bs, buf) == 0);
|
||||
CHECK(ptr_diff_bytes(s0, buf) == 0);
|
||||
CHECK(ptr_diff_bytes(sp, buf) == 0);
|
||||
CHECK(ptr_diff_bytes(bs, buf) == 0);
|
||||
//
|
||||
CHECK(ptr_diff_bytes(s0, bp) == 0);
|
||||
CHECK(ptr_diff_bytes(s0, sp) == 0);
|
||||
CHECK(ptr_diff_bytes(s0, ss) == 0);
|
||||
//
|
||||
CHECK(ptr_diff_bytes(s0c, b0c) == 0);
|
||||
CHECK(ptr_diff_bytes(spc, bpc) == 0);
|
||||
CHECK(ptr_diff_bytes(ssc, bsc) == 0);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
#if !defined(DOCTEST_CONFIG_DISABLE)
|
||||
namespace {
|
||||
int my_memcmp_v1(XSPAN_P(const void) a, XSPAN_0(const void) b, size_t n) {
|
||||
if (b == nullptr)
|
||||
return -2;
|
||||
XSPAN_0(const void) x(a);
|
||||
return memcmp(x, b, n);
|
||||
}
|
||||
int my_memcmp_v2(XSPAN_P(const char) a, XSPAN_0(const char) b, size_t n) {
|
||||
if (a == b)
|
||||
return 0;
|
||||
if (b == nullptr)
|
||||
return -2;
|
||||
a += 1;
|
||||
b -= 1;
|
||||
XSPAN_0(const char) x(a);
|
||||
XSPAN_0(const char) y = b;
|
||||
return memcmp(x, y, n);
|
||||
}
|
||||
} // namespace
|
||||
#endif
|
||||
|
||||
TEST_CASE("PtrOrSpan") {
|
||||
static const char buf[4] = {0, 1, 2, 3};
|
||||
CHECK(my_memcmp_v1(buf, nullptr, 4) == -2);
|
||||
CHECK(my_memcmp_v2(buf + 4, buf + 4, 999) == 0);
|
||||
CHECK(my_memcmp_v2(buf, buf + 2, 3) == 0);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
TEST_CASE("PtrOrSpan char") {
|
||||
char real_buf[2 + 8 + 2] = {126, 127, 0, 1, 2, 3, 4, 5, 6, 7, 124, 125};
|
||||
char *buf = real_buf + 2;
|
||||
XSPAN_P(char) a(buf, XSpanSizeInBytes(8));
|
||||
XSPAN_P(char) b = a.subspan(0, 7);
|
||||
XSPAN_P(char) c = (b + 1).subspan(0, 6);
|
||||
a += 1;
|
||||
CHECK(*a == 1);
|
||||
*a++ += 1;
|
||||
*b++ = 1;
|
||||
CHECK(a == buf + 2);
|
||||
CHECK(b == buf + 1);
|
||||
CHECK(c == buf + 1);
|
||||
CHECK(*b == 2);
|
||||
CHECK(*c == 2);
|
||||
CHECK(a.raw_size_in_bytes() == 8u);
|
||||
CHECK(b.raw_size_in_bytes() == 7u);
|
||||
CHECK(c.raw_size_in_bytes() == 6u);
|
||||
CHECK(a.raw_base() == buf);
|
||||
CHECK(b.raw_base() == buf);
|
||||
CHECK(c.raw_base() == buf + 1);
|
||||
#ifdef UPX_VERSION_HEX
|
||||
CHECK(get_le32(a) != 0);
|
||||
#endif
|
||||
++c;
|
||||
c++;
|
||||
#ifdef UPX_VERSION_HEX
|
||||
CHECK(get_le32(c) != 0);
|
||||
#endif
|
||||
++c;
|
||||
#ifdef UPX_VERSION_HEX
|
||||
CHECK_THROWS(get_le32(c));
|
||||
#endif
|
||||
++b;
|
||||
b++;
|
||||
b += 4;
|
||||
CHECK(b.raw_ptr() == buf + 7);
|
||||
CHECK_THROWS(*b);
|
||||
CHECK(a.raw_size_in_bytes() == 8u);
|
||||
a = b;
|
||||
CHECK(a.raw_size_in_bytes() == 8u);
|
||||
CHECK(a.raw_ptr() == buf + 7);
|
||||
a++;
|
||||
CHECK_THROWS(*a);
|
||||
CHECK_THROWS(raw_bytes(a, 1));
|
||||
a = b;
|
||||
CHECK_THROWS(a = c);
|
||||
*a = 0;
|
||||
a = buf;
|
||||
#ifdef UPX_VERSION_HEX
|
||||
CHECK(upx_safe_strlen(a) == 7u);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_CASE("PtrOrSpan int") {
|
||||
int buf[8] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||
XSPAN_P(int) a(buf, XSpanCount(8));
|
||||
CHECK(a.raw_size_in_bytes() == 8 * sizeof(int));
|
||||
XSPAN_P(int) b = a.subspan(0, 7);
|
||||
CHECK(b.raw_size_in_bytes() == 7 * sizeof(int));
|
||||
XSPAN_P(int) c = (b + 1).subspan(0, 6);
|
||||
CHECK(c.raw_size_in_bytes() == 6 * sizeof(int));
|
||||
a += 1;
|
||||
CHECK(*a == 1);
|
||||
CHECK(*a++ == 1);
|
||||
CHECK(*++a == 3);
|
||||
CHECK(--*a == 2);
|
||||
CHECK(*a-- == 2);
|
||||
CHECK(*b == 0);
|
||||
CHECK(*c == 1);
|
||||
a = buf + 7;
|
||||
#ifdef UPX_VERSION_HEX
|
||||
CHECK(get_le32(a) == ne32_to_le32(7));
|
||||
#endif
|
||||
a++;
|
||||
#ifdef UPX_VERSION_HEX
|
||||
CHECK_THROWS(get_le32(a));
|
||||
#endif
|
||||
CHECK_THROWS(raw_bytes(a, 1));
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
// codegen
|
||||
**************************************************************************/
|
||||
|
||||
namespace {
|
||||
template <class T>
|
||||
__acc_static_noinline int foo(T p) {
|
||||
unsigned r = 0;
|
||||
r += *p++;
|
||||
r += *++p;
|
||||
p += 3;
|
||||
r += *p;
|
||||
return r;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
XSPAN_0(T)
|
||||
make_span_0(T *ptr, size_t count) {
|
||||
return PtrOrSpanOrNull<T>(ptr, count);
|
||||
}
|
||||
template <class T>
|
||||
XSPAN_P(T)
|
||||
make_span_p(T *ptr, size_t count) {
|
||||
return PtrOrSpan<T>(ptr, count);
|
||||
}
|
||||
template <class T>
|
||||
XSPAN_S(T)
|
||||
make_span_s(T *ptr, size_t count) {
|
||||
return Span<T>(ptr, count);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("Span codegen") {
|
||||
char buf[8] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||
CHECK(foo(buf) == 0 + 2 + 5);
|
||||
CHECK(foo(make_span_0(buf, 8)) == 0 + 2 + 5);
|
||||
CHECK(foo(make_span_p(buf, 8)) == 0 + 2 + 5);
|
||||
CHECK(foo(make_span_s(buf, 8)) == 0 + 2 + 5);
|
||||
}
|
||||
|
||||
#endif // WITH_XSPAN >= 2
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -21,68 +20,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.com> <ml1050@users.sourceforge.net>
|
||||
Markus F.X.J. Oberhumer
|
||||
<markus@oberhumer.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
#include "../conf.h"
|
||||
#include "compress.h"
|
||||
#include "mem.h"
|
||||
#include <zlib.h>
|
||||
|
||||
#include "../util/membuffer.h"
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
unsigned upx_adler32(const void *buf, unsigned len, unsigned adler)
|
||||
{
|
||||
unsigned upx_adler32(const void *buf, unsigned len, unsigned adler) {
|
||||
if (len == 0)
|
||||
return adler;
|
||||
assert(buf != NULL);
|
||||
#if 0
|
||||
return adler32(adler, (const Bytef *) buf, len); // zlib
|
||||
#elif defined(WITH_UCL)
|
||||
return ucl_adler32(adler, (const ucl_bytep) buf, len);
|
||||
assert(buf != nullptr);
|
||||
#if 1
|
||||
return upx_ucl_adler32(buf, len, adler);
|
||||
#else
|
||||
# error
|
||||
return upx_zlib_adler32(buf, len, adler);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if 0 /* UNUSED */
|
||||
#if 0 // UNUSED
|
||||
unsigned upx_crc32(const void *buf, unsigned len, unsigned crc)
|
||||
{
|
||||
if (len == 0)
|
||||
return crc;
|
||||
assert(buf != NULL);
|
||||
#if 0
|
||||
return crc32(crc, (const Bytef *) buf, len); // zlib
|
||||
#elif defined(WITH_UCL)
|
||||
return ucl_crc32(crc, (const ucl_bytep) buf, len);
|
||||
assert(buf != nullptr);
|
||||
#if 1
|
||||
return upx_ucl_crc32(buf, len, crc);
|
||||
#else
|
||||
# error
|
||||
return upx_zlib_crc32(buf, len, crc);
|
||||
#endif
|
||||
}
|
||||
#endif /* UNUSED */
|
||||
|
||||
#endif // UNUSED
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
int upx_compress ( const upx_bytep src, unsigned src_len,
|
||||
upx_bytep dst, unsigned* dst_len,
|
||||
upx_callback_p cb,
|
||||
int method, int level,
|
||||
const upx_compress_config_t *cconf,
|
||||
upx_compress_result_t *cresult )
|
||||
{
|
||||
int upx_compress(const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned *dst_len,
|
||||
upx_callback_p cb, int method, int level, const upx_compress_config_t *cconf,
|
||||
upx_compress_result_t *cresult) {
|
||||
int r = UPX_E_ERROR;
|
||||
upx_compress_result_t cresult_buffer;
|
||||
|
||||
assert(method > 0); assert(level > 0);
|
||||
assert(method > 0);
|
||||
assert(level > 0);
|
||||
|
||||
#if 1
|
||||
// set available bytes in dst
|
||||
@@ -99,76 +85,77 @@ int upx_compress ( const upx_bytep src, unsigned src_len,
|
||||
cresult = &cresult_buffer;
|
||||
memset(cresult, 0, sizeof(*cresult));
|
||||
#if 1
|
||||
// debug
|
||||
cresult->method = method;
|
||||
cresult->level = level;
|
||||
cresult->u_len = src_len;
|
||||
cresult->c_len = 0;
|
||||
// debugging aid
|
||||
cresult->debug.method = method;
|
||||
cresult->debug.level = level;
|
||||
cresult->debug.u_len = src_len;
|
||||
cresult->debug.c_len = 0;
|
||||
#endif
|
||||
|
||||
if (0) {
|
||||
if (__acc_cte(false)) {
|
||||
}
|
||||
#if defined(WITH_LZMA)
|
||||
#if (WITH_LZMA)
|
||||
else if (M_IS_LZMA(method))
|
||||
r = upx_lzma_compress(src, src_len, dst, dst_len,
|
||||
cb, method, level, cconf, cresult);
|
||||
r = upx_lzma_compress(src, src_len, dst, dst_len, cb, method, level, cconf, cresult);
|
||||
#endif
|
||||
#if defined(WITH_NRV)
|
||||
else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method))
|
||||
r = upx_nrv_compress(src, src_len, dst, dst_len,
|
||||
cb, method, level, cconf, cresult);
|
||||
#if (WITH_NRV)
|
||||
else if ((M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method)) && !opt->prefer_ucl)
|
||||
r = upx_nrv_compress(src, src_len, dst, dst_len, cb, method, level, cconf, cresult);
|
||||
#endif
|
||||
#if defined(WITH_UCL)
|
||||
#if (WITH_UCL)
|
||||
else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method))
|
||||
r = upx_ucl_compress(src, src_len, dst, dst_len,
|
||||
cb, method, level, cconf, cresult);
|
||||
r = upx_ucl_compress(src, src_len, dst, dst_len, cb, method, level, cconf, cresult);
|
||||
#endif
|
||||
#if (WITH_ZSTD)
|
||||
else if (M_IS_ZSTD(method))
|
||||
r = upx_zstd_compress(src, src_len, dst, dst_len, cb, method, level, cconf, cresult);
|
||||
#endif
|
||||
else {
|
||||
throwInternalError("unknown compression method");
|
||||
}
|
||||
|
||||
#if 1
|
||||
// debug
|
||||
cresult->c_len = *dst_len;
|
||||
// debugging aid
|
||||
cresult->debug.c_len = *dst_len;
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
int upx_decompress ( const upx_bytep src, unsigned src_len,
|
||||
upx_bytep dst, unsigned* dst_len,
|
||||
int method,
|
||||
const upx_compress_result_t *cresult )
|
||||
{
|
||||
int upx_decompress(const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned *dst_len,
|
||||
int method, const upx_compress_result_t *cresult) {
|
||||
int r = UPX_E_ERROR;
|
||||
|
||||
assert(*dst_len > 0);
|
||||
assert(src_len < *dst_len); // must be compressed
|
||||
|
||||
if (cresult && cresult->method == 0)
|
||||
cresult = NULL;
|
||||
if (cresult && cresult->debug.method == 0)
|
||||
cresult = nullptr;
|
||||
|
||||
if (0) {
|
||||
if (__acc_cte(false)) {
|
||||
}
|
||||
#if defined(WITH_LZMA)
|
||||
#if (WITH_LZMA)
|
||||
else if (M_IS_LZMA(method))
|
||||
r = upx_lzma_decompress(src, src_len, dst, dst_len, method, cresult);
|
||||
#endif
|
||||
#if defined(WITH_NRV)
|
||||
else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method))
|
||||
#if (WITH_NRV)
|
||||
else if ((M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method)) && !opt->prefer_ucl)
|
||||
r = upx_nrv_decompress(src, src_len, dst, dst_len, method, cresult);
|
||||
#endif
|
||||
#if defined(WITH_UCL)
|
||||
#if (WITH_UCL)
|
||||
else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method))
|
||||
r = upx_ucl_decompress(src, src_len, dst, dst_len, method, cresult);
|
||||
#endif
|
||||
#if defined(WITH_ZLIB)
|
||||
#if (WITH_ZLIB)
|
||||
else if (M_IS_DEFLATE(method))
|
||||
r = upx_zlib_decompress(src, src_len, dst, dst_len, method, cresult);
|
||||
#endif
|
||||
#if (WITH_ZSTD)
|
||||
else if (M_IS_ZSTD(method))
|
||||
r = upx_zstd_decompress(src, src_len, dst, dst_len, method, cresult);
|
||||
#endif
|
||||
else {
|
||||
throwInternalError("unknown decompression method");
|
||||
@@ -177,41 +164,39 @@ int upx_decompress ( const upx_bytep src, unsigned src_len,
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
int upx_test_overlap ( const upx_bytep buf,
|
||||
const upx_bytep tbuf,
|
||||
unsigned src_off, unsigned src_len,
|
||||
unsigned* dst_len,
|
||||
int method,
|
||||
const upx_compress_result_t *cresult )
|
||||
{
|
||||
int upx_test_overlap(const upx_bytep buf, const upx_bytep tbuf, unsigned src_off, unsigned src_len,
|
||||
unsigned *dst_len, int method, const upx_compress_result_t *cresult) {
|
||||
int r = UPX_E_ERROR;
|
||||
|
||||
if (cresult && cresult->method == 0)
|
||||
cresult = NULL;
|
||||
if (cresult && cresult->debug.method == 0)
|
||||
cresult = nullptr;
|
||||
|
||||
assert(*dst_len > 0);
|
||||
assert(src_len < *dst_len); // must be compressed
|
||||
unsigned overlap_overhead = src_off + src_len - *dst_len;
|
||||
assert((int)overlap_overhead > 0);
|
||||
assert((int) overlap_overhead > 0);
|
||||
|
||||
if (0) {
|
||||
if (__acc_cte(false)) {
|
||||
}
|
||||
#if defined(WITH_LZMA)
|
||||
#if (WITH_LZMA)
|
||||
else if (M_IS_LZMA(method))
|
||||
r = upx_lzma_test_overlap(buf, tbuf, src_off, src_len, dst_len, method, cresult);
|
||||
#endif
|
||||
#if defined(WITH_NRV)
|
||||
else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method))
|
||||
#if (WITH_NRV)
|
||||
else if ((M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method)) && !opt->prefer_ucl)
|
||||
r = upx_nrv_test_overlap(buf, tbuf, src_off, src_len, dst_len, method, cresult);
|
||||
#endif
|
||||
#if defined(WITH_UCL)
|
||||
#if (WITH_UCL)
|
||||
else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method))
|
||||
r = upx_ucl_test_overlap(buf, tbuf, src_off, src_len, dst_len, method, cresult);
|
||||
#endif
|
||||
#if (WITH_ZSTD)
|
||||
else if (M_IS_ZSTD(method))
|
||||
r = upx_zstd_test_overlap(buf, tbuf, src_off, src_len, dst_len, method, cresult);
|
||||
#endif
|
||||
else {
|
||||
throwInternalError("unknown decompression method");
|
||||
@@ -220,8 +205,4 @@ int upx_test_overlap ( const upx_bytep buf,
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et:nowrap
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -21,20 +20,42 @@
|
||||
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@users.sourceforge.net>
|
||||
Markus F.X.J. Oberhumer
|
||||
<markus@oberhumer.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __UPX_COMPRESS_H
|
||||
#define __UPX_COMPRESS_H
|
||||
|
||||
#pragma once
|
||||
#ifndef UPX_COMPRESS_H__
|
||||
#define UPX_COMPRESS_H__ 1
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
#if defined(WITH_LZMA)
|
||||
#if (WITH_BZIP2)
|
||||
int upx_bzip2_init(void);
|
||||
const char *upx_bzip2_version_string(void);
|
||||
int upx_bzip2_compress ( const upx_bytep src, unsigned src_len,
|
||||
upx_bytep dst, unsigned* dst_len,
|
||||
upx_callback_p cb,
|
||||
int method, int level,
|
||||
const upx_compress_config_t *cconf,
|
||||
upx_compress_result_t *cresult );
|
||||
int upx_bzip2_decompress ( const upx_bytep src, unsigned src_len,
|
||||
upx_bytep dst, unsigned* dst_len,
|
||||
int method,
|
||||
const upx_compress_result_t *cresult );
|
||||
int upx_bzip2_test_overlap ( const upx_bytep buf,
|
||||
const upx_bytep tbuf,
|
||||
unsigned src_off, unsigned src_len,
|
||||
unsigned* dst_len,
|
||||
int method,
|
||||
const upx_compress_result_t *cresult );
|
||||
#endif
|
||||
|
||||
|
||||
#if (WITH_LZMA)
|
||||
int upx_lzma_init(void);
|
||||
const char *upx_lzma_version_string(void);
|
||||
int upx_lzma_compress ( const upx_bytep src, unsigned src_len,
|
||||
upx_bytep dst, unsigned* dst_len,
|
||||
@@ -55,7 +76,8 @@ int upx_lzma_test_overlap ( const upx_bytep buf,
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(WITH_NRV)
|
||||
#if (WITH_NRV)
|
||||
int upx_nrv_init(void);
|
||||
const char *upx_nrv_version_string(void);
|
||||
int upx_nrv_compress ( const upx_bytep src, unsigned src_len,
|
||||
upx_bytep dst, unsigned* dst_len,
|
||||
@@ -76,7 +98,8 @@ int upx_nrv_test_overlap ( const upx_bytep buf,
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(WITH_UCL)
|
||||
#if (WITH_UCL)
|
||||
int upx_ucl_init(void);
|
||||
const char *upx_ucl_version_string(void);
|
||||
int upx_ucl_compress ( const upx_bytep src, unsigned src_len,
|
||||
upx_bytep dst, unsigned* dst_len,
|
||||
@@ -94,9 +117,13 @@ int upx_ucl_test_overlap ( const upx_bytep buf,
|
||||
unsigned* dst_len,
|
||||
int method,
|
||||
const upx_compress_result_t *cresult );
|
||||
unsigned upx_ucl_adler32(const void *buf, unsigned len, unsigned adler);
|
||||
unsigned upx_ucl_crc32 (const void *buf, unsigned len, unsigned crc);
|
||||
#endif
|
||||
|
||||
#if defined(WITH_ZLIB)
|
||||
|
||||
#if (WITH_ZLIB)
|
||||
int upx_zlib_init(void);
|
||||
const char *upx_zlib_version_string(void);
|
||||
int upx_zlib_compress ( const upx_bytep src, unsigned src_len,
|
||||
upx_bytep dst, unsigned* dst_len,
|
||||
@@ -114,13 +141,33 @@ int upx_zlib_test_overlap ( const upx_bytep buf,
|
||||
unsigned* dst_len,
|
||||
int method,
|
||||
const upx_compress_result_t *cresult );
|
||||
unsigned upx_zlib_adler32(const void *buf, unsigned len, unsigned adler);
|
||||
unsigned upx_zlib_crc32 (const void *buf, unsigned len, unsigned crc);
|
||||
#endif
|
||||
|
||||
|
||||
#if (WITH_ZSTD)
|
||||
int upx_zstd_init(void);
|
||||
const char *upx_zstd_version_string(void);
|
||||
int upx_zstd_compress ( const upx_bytep src, unsigned src_len,
|
||||
upx_bytep dst, unsigned* dst_len,
|
||||
upx_callback_p cb,
|
||||
int method, int level,
|
||||
const upx_compress_config_t *cconf,
|
||||
upx_compress_result_t *cresult );
|
||||
int upx_zstd_decompress ( const upx_bytep src, unsigned src_len,
|
||||
upx_bytep dst, unsigned* dst_len,
|
||||
int method,
|
||||
const upx_compress_result_t *cresult );
|
||||
int upx_zstd_test_overlap ( const upx_bytep buf,
|
||||
const upx_bytep tbuf,
|
||||
unsigned src_off, unsigned src_len,
|
||||
unsigned* dst_len,
|
||||
int method,
|
||||
const upx_compress_result_t *cresult );
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* already included */
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -0,0 +1,544 @@
|
||||
/* compress_lzma.cpp --
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
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
|
||||
<markus@oberhumer.com>
|
||||
*/
|
||||
|
||||
#include "../conf.h"
|
||||
#include "compress.h"
|
||||
#include "../util/membuffer.h"
|
||||
|
||||
#if (ACC_CC_CLANG)
|
||||
#pragma clang diagnostic ignored "-Wshadow"
|
||||
#endif
|
||||
#if (ACC_CC_GNUC >= 0x040200)
|
||||
#pragma GCC diagnostic ignored "-Wshadow"
|
||||
#endif
|
||||
#if (ACC_CC_MSC)
|
||||
#pragma warning(disable : 4456) // -Wno-shadow
|
||||
#endif
|
||||
#if (ACC_CC_MSC && (_MSC_VER < 1900))
|
||||
#pragma warning(disable : 4127) // warning C4127: conditional expression is constant
|
||||
#endif
|
||||
|
||||
void lzma_compress_config_t::reset() {
|
||||
pos_bits.reset();
|
||||
lit_pos_bits.reset();
|
||||
lit_context_bits.reset();
|
||||
dict_size.reset();
|
||||
fast_mode = 2;
|
||||
num_fast_bytes.reset();
|
||||
match_finder_cycles = 0;
|
||||
|
||||
max_num_probs = 0;
|
||||
}
|
||||
|
||||
// INFO: the LZMA SDK is covered by a permissive license which allows
|
||||
// using unmodified LZMA source code in UPX and the UPX stubs.
|
||||
// See SPECIAL EXCEPTION below.
|
||||
//
|
||||
// Quoting from lzma-4.43/lzma.txt:
|
||||
//
|
||||
// LICENSE
|
||||
// -------
|
||||
//
|
||||
// LZMA SDK is available under any of the following licenses:
|
||||
//
|
||||
// 1) GNU Lesser General Public License (GNU LGPL)
|
||||
// 2) Common Public License (CPL)
|
||||
// 3) Simplified license for unmodified code (read SPECIAL EXCEPTION)
|
||||
// 4) Proprietary license
|
||||
//
|
||||
// It means that you can select one of these four options and follow rules
|
||||
// of that license.
|
||||
//
|
||||
// 1,2) GNU LGPL and CPL licenses are pretty similar and both these
|
||||
// licenses are classified as
|
||||
// - "Free software licenses" at http://www.gnu.org/
|
||||
// - "OSI-approved" at http://www.opensource.org/
|
||||
//
|
||||
// 3) SPECIAL EXCEPTION
|
||||
//
|
||||
// Igor Pavlov, as the author of this code, expressly permits you
|
||||
// to statically or dynamically link your code (or bind by name)
|
||||
// to the files from LZMA SDK without subjecting your linked
|
||||
// code to the terms of the CPL or GNU LGPL.
|
||||
// Any modifications or additions to files from LZMA SDK, however,
|
||||
// are subject to the GNU LGPL or CPL terms.
|
||||
//
|
||||
// SPECIAL EXCEPTION allows you to use LZMA SDK in applications with closed code,
|
||||
// while you keep LZMA SDK code unmodified.
|
||||
|
||||
/*************************************************************************
|
||||
// compress defaults
|
||||
**************************************************************************/
|
||||
|
||||
static bool prepare_result(lzma_compress_result_t *res, unsigned src_len, int method, int level,
|
||||
const lzma_compress_config_t *lcconf) {
|
||||
// setup defaults
|
||||
res->pos_bits = 2; // 0 .. 4
|
||||
res->lit_pos_bits = 0; // 0 .. 4
|
||||
res->lit_context_bits = 3; // 0 .. 8
|
||||
res->dict_size = 4 * 1024 * 1024; // 1 .. 2**30
|
||||
res->fast_mode = 2; // 0 .. 2
|
||||
res->num_fast_bytes = 64; // 5 .. 273
|
||||
res->match_finder_cycles = 0;
|
||||
// UPX overrides
|
||||
res->pos_bits = lzma_compress_config_t::pos_bits_t::default_value;
|
||||
res->lit_pos_bits = lzma_compress_config_t::lit_pos_bits_t::default_value;
|
||||
res->lit_context_bits = lzma_compress_config_t::lit_context_bits_t::default_value;
|
||||
res->dict_size = lzma_compress_config_t::dict_size_t::default_value;
|
||||
res->num_fast_bytes = lzma_compress_config_t::num_fast_bytes_t::default_value;
|
||||
// method overrides
|
||||
if (method >= 0x100) {
|
||||
res->pos_bits = (method >> 16) & 15;
|
||||
res->lit_pos_bits = (method >> 12) & 15;
|
||||
res->lit_context_bits = (method >> 8) & 15;
|
||||
}
|
||||
#if 0
|
||||
// DEBUG - set sizes so that we use a maxmimum amount of stack.
|
||||
// These settings cause res->num_probs == 3147574, i.e. we will
|
||||
// need about 6 MiB of stack during runtime decompression.
|
||||
res->lit_pos_bits = 4;
|
||||
res->lit_context_bits = 8;
|
||||
#endif
|
||||
|
||||
// TODO: tune these settings according to level
|
||||
switch (level) {
|
||||
case 1:
|
||||
res->dict_size = 256 * 1024;
|
||||
res->fast_mode = 0;
|
||||
res->num_fast_bytes = 8;
|
||||
break;
|
||||
case 2:
|
||||
res->dict_size = 256 * 1024;
|
||||
res->fast_mode = 0;
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
break;
|
||||
case 5:
|
||||
break;
|
||||
case 6:
|
||||
break;
|
||||
case 7:
|
||||
break;
|
||||
case 8:
|
||||
break;
|
||||
case 9:
|
||||
res->dict_size = 8 * 1024 * 1024;
|
||||
break;
|
||||
case 10:
|
||||
res->dict_size = src_len;
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
|
||||
// cconf overrides
|
||||
if (lcconf) {
|
||||
oassign(res->pos_bits, lcconf->pos_bits);
|
||||
oassign(res->lit_pos_bits, lcconf->lit_pos_bits);
|
||||
oassign(res->lit_context_bits, lcconf->lit_context_bits);
|
||||
oassign(res->dict_size, lcconf->dict_size);
|
||||
oassign(res->num_fast_bytes, lcconf->num_fast_bytes);
|
||||
}
|
||||
|
||||
// limit dictionary size
|
||||
if (res->dict_size > src_len)
|
||||
res->dict_size = src_len;
|
||||
|
||||
// limit num_probs
|
||||
if (lcconf && lcconf->max_num_probs) {
|
||||
for (;;) {
|
||||
unsigned n = 1846 + (768u << (res->lit_context_bits + res->lit_pos_bits));
|
||||
if (n <= lcconf->max_num_probs)
|
||||
break;
|
||||
if (res->lit_pos_bits > res->lit_context_bits) {
|
||||
if (res->lit_pos_bits == 0)
|
||||
goto error;
|
||||
res->lit_pos_bits -= 1;
|
||||
} else {
|
||||
if (res->lit_context_bits == 0)
|
||||
goto error;
|
||||
res->lit_context_bits -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lzma_compress_config_t::pos_bits_t::assertValue(res->pos_bits);
|
||||
lzma_compress_config_t::lit_pos_bits_t::assertValue(res->lit_pos_bits);
|
||||
lzma_compress_config_t::lit_context_bits_t::assertValue(res->lit_context_bits);
|
||||
lzma_compress_config_t::dict_size_t::assertValue(res->dict_size);
|
||||
lzma_compress_config_t::num_fast_bytes_t::assertValue(res->num_fast_bytes);
|
||||
|
||||
res->num_probs = 1846 + (768u << (res->lit_context_bits + res->lit_pos_bits));
|
||||
// printf("\nlzma_compress config: %u %u %u %u %u\n", res->pos_bits, res->lit_pos_bits,
|
||||
// res->lit_context_bits, res->dict_size, res->num_probs);
|
||||
return true;
|
||||
|
||||
error:
|
||||
return false;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
// compress - cruft because of pseudo-COM layer
|
||||
**************************************************************************/
|
||||
|
||||
#undef MSDOS
|
||||
#undef OS2
|
||||
#undef _WIN32
|
||||
#undef _WIN32_WCE
|
||||
#undef COMPRESS_MF_MT
|
||||
#undef _NO_EXCEPTIONS
|
||||
#undef NULL
|
||||
#define NULL nullptr
|
||||
#include <lzma-sdk/C/Common/MyInitGuid.h>
|
||||
// #include <lzma-sdk/C/7zip/Compress/LZMA/LZMADecoder.h>
|
||||
#include <lzma-sdk/C/7zip/Compress/LZMA/LZMAEncoder.h>
|
||||
|
||||
namespace MyLzma {
|
||||
|
||||
struct InStream final : public ISequentialInStream, public CMyUnknownImp {
|
||||
virtual ~InStream() {}
|
||||
MY_UNKNOWN_IMP
|
||||
const Byte *b_buf = nullptr;
|
||||
size_t b_size;
|
||||
size_t b_pos;
|
||||
void Init(const Byte *data, size_t size) {
|
||||
b_buf = data;
|
||||
b_size = size;
|
||||
b_pos = 0;
|
||||
}
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) override;
|
||||
};
|
||||
|
||||
STDMETHODIMP InStream::Read(void *data, UInt32 size, UInt32 *processedSize) {
|
||||
size_t remain = b_size - b_pos;
|
||||
if (size > remain)
|
||||
size = (UInt32) remain;
|
||||
memmove(data, b_buf + b_pos, size);
|
||||
b_pos += size;
|
||||
if (processedSize != nullptr)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
struct OutStream final : public ISequentialOutStream, public CMyUnknownImp {
|
||||
virtual ~OutStream() {}
|
||||
MY_UNKNOWN_IMP
|
||||
Byte *b_buf = nullptr;
|
||||
size_t b_size;
|
||||
size_t b_pos;
|
||||
bool overflow;
|
||||
void Init(Byte *data, size_t size) {
|
||||
b_buf = data;
|
||||
b_size = size;
|
||||
b_pos = 0;
|
||||
overflow = false;
|
||||
}
|
||||
HRESULT WriteByte(Byte c) {
|
||||
if (b_pos >= b_size) {
|
||||
overflow = true;
|
||||
return E_FAIL;
|
||||
}
|
||||
b_buf[b_pos++] = c;
|
||||
return S_OK;
|
||||
}
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) override;
|
||||
};
|
||||
|
||||
STDMETHODIMP OutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) {
|
||||
size_t remain = b_size - b_pos;
|
||||
if (size > remain)
|
||||
size = (UInt32) remain, overflow = true;
|
||||
memmove(b_buf + b_pos, data, size);
|
||||
b_pos += size;
|
||||
if (processedSize != nullptr)
|
||||
*processedSize = size;
|
||||
return overflow ? E_FAIL : S_OK;
|
||||
}
|
||||
|
||||
struct ProgressInfo final : public ICompressProgressInfo, public CMyUnknownImp {
|
||||
virtual ~ProgressInfo() {}
|
||||
MY_UNKNOWN_IMP
|
||||
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) override;
|
||||
upx_callback_p cb = nullptr;
|
||||
};
|
||||
|
||||
STDMETHODIMP ProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) {
|
||||
if (cb && cb->nprogress)
|
||||
cb->nprogress(cb, (unsigned) *inSize, (unsigned) *outSize);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
} // namespace MyLzma
|
||||
|
||||
#include <lzma-sdk/C/Common/Alloc.cpp>
|
||||
#include <lzma-sdk/C/Common/CRC.cpp>
|
||||
// #include <lzma-sdk/C/7zip/Common/InBuffer.cpp>
|
||||
#include <lzma-sdk/C/7zip/Common/OutBuffer.cpp>
|
||||
#include <lzma-sdk/C/7zip/Common/StreamUtils.cpp>
|
||||
#include <lzma-sdk/C/7zip/Compress/LZ/LZInWindow.cpp>
|
||||
// #include <lzma-sdk/C/7zip/Compress/LZ/LZOutWindow.cpp>
|
||||
// #include <lzma-sdk/C/7zip/Compress/LZMA/LZMADecoder.cpp>
|
||||
#include <lzma-sdk/C/7zip/Compress/LZMA/LZMAEncoder.cpp>
|
||||
#include <lzma-sdk/C/7zip/Compress/RangeCoder/RangeCoderBit.cpp>
|
||||
#undef RC_NORMALIZE
|
||||
|
||||
int upx_lzma_compress(const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned *dst_len,
|
||||
upx_callback_p cb, int method, int level,
|
||||
const upx_compress_config_t *cconf_parm, upx_compress_result_t *cresult) {
|
||||
assert(M_IS_LZMA(method));
|
||||
assert(level > 0);
|
||||
assert(cresult != nullptr);
|
||||
|
||||
int r = UPX_E_ERROR;
|
||||
HRESULT rh;
|
||||
const lzma_compress_config_t *const lcconf = cconf_parm ? &cconf_parm->conf_lzma : nullptr;
|
||||
lzma_compress_result_t *const res = &cresult->result_lzma;
|
||||
|
||||
MyLzma::InStream is;
|
||||
is.AddRef();
|
||||
is.Init(src, src_len);
|
||||
MyLzma::OutStream os;
|
||||
os.AddRef();
|
||||
os.Init(dst, *dst_len);
|
||||
MyLzma::ProgressInfo progress;
|
||||
progress.AddRef();
|
||||
progress.cb = cb; // progress.Init()
|
||||
|
||||
NCompress::NLZMA::CEncoder enc;
|
||||
const PROPID propIDs[8] = {
|
||||
NCoderPropID::kPosStateBits, // 0 pb _posStateBits(2)
|
||||
NCoderPropID::kLitPosBits, // 1 lp _numLiteralPosStateBits(0)
|
||||
NCoderPropID::kLitContextBits, // 2 lc _numLiteralContextBits(3)
|
||||
NCoderPropID::kDictionarySize, // 3 ds
|
||||
NCoderPropID::kAlgorithm, // 4 fm _fastmode
|
||||
NCoderPropID::kNumFastBytes, // 5 fb
|
||||
NCoderPropID::kMatchFinderCycles, // 6 mfc _matchFinderCycles, _cutValue
|
||||
NCoderPropID::kMatchFinder // 7 mf
|
||||
};
|
||||
PROPVARIANT pr[8];
|
||||
const unsigned nprops = 8;
|
||||
if (!prepare_result(res, src_len, method, level, lcconf))
|
||||
goto error;
|
||||
pr[0].vt = pr[1].vt = pr[2].vt = pr[3].vt = pr[4].vt = pr[5].vt = pr[6].vt = VT_UI4;
|
||||
pr[7].vt = VT_BSTR;
|
||||
pr[0].uintVal = res->pos_bits;
|
||||
pr[1].uintVal = res->lit_pos_bits;
|
||||
pr[2].uintVal = res->lit_context_bits;
|
||||
pr[3].uintVal = res->dict_size;
|
||||
pr[4].uintVal = res->fast_mode;
|
||||
pr[5].uintVal = res->num_fast_bytes;
|
||||
pr[6].uintVal = res->match_finder_cycles;
|
||||
static const wchar_t matchfinder[] = L"BT4";
|
||||
assert(NCompress::NLZMA::FindMatchFinder(matchfinder) >= 0);
|
||||
pr[7].bstrVal = ACC_PCAST(BSTR, ACC_UNCONST_CAST(wchar_t *, matchfinder));
|
||||
|
||||
try {
|
||||
if (enc.SetCoderProperties(propIDs, pr, nprops) != S_OK)
|
||||
goto error;
|
||||
// encode properties in LZMA-style (5 bytes)
|
||||
if (enc.WriteCoderProperties(&os) != S_OK)
|
||||
goto error;
|
||||
if (os.overflow) {
|
||||
// r = UPX_E_OUTPUT_OVERRUN;
|
||||
r = UPX_E_NOT_COMPRESSIBLE;
|
||||
goto error;
|
||||
}
|
||||
assert(os.b_pos == 5);
|
||||
|
||||
// reset and encode properties in UPX-style (2 bytes)
|
||||
os.b_pos = 0;
|
||||
// UPX extra stuff in first byte: 5 high bits convenience for stub decompressor
|
||||
unsigned t = res->lit_context_bits + res->lit_pos_bits;
|
||||
os.WriteByte(Byte((t << 3) | res->pos_bits));
|
||||
os.WriteByte(Byte((res->lit_pos_bits << 4) | (res->lit_context_bits)));
|
||||
|
||||
// compress
|
||||
rh = enc.Code(&is, &os, nullptr, nullptr, &progress);
|
||||
|
||||
} catch (...) {
|
||||
rh = E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
assert(is.b_pos <= src_len);
|
||||
assert(os.b_pos <= *dst_len);
|
||||
if (rh == E_OUTOFMEMORY)
|
||||
r = UPX_E_OUT_OF_MEMORY;
|
||||
else if (os.overflow) {
|
||||
assert(os.b_pos == *dst_len);
|
||||
// r = UPX_E_OUTPUT_OVERRUN;
|
||||
r = UPX_E_NOT_COMPRESSIBLE;
|
||||
} else if (rh == S_OK) {
|
||||
assert(is.b_pos == src_len);
|
||||
r = UPX_E_OK;
|
||||
}
|
||||
|
||||
error:
|
||||
*dst_len = (unsigned) os.b_pos;
|
||||
// printf("\nlzma_compress: %d: %u %u %u %u %u, %u - > %u\n", r, res->pos_bits,
|
||||
// res->lit_pos_bits,
|
||||
// res->lit_context_bits, res->dict_size, res->num_probs, src_len, *dst_len);
|
||||
// printf("%u %u %u\n", is.__m_RefCount, os.__m_RefCount, progress.__m_RefCount);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
// decompress
|
||||
**************************************************************************/
|
||||
|
||||
#undef _LZMA_IN_CB
|
||||
#undef _LZMA_OUT_READ
|
||||
#undef _LZMA_PROB32
|
||||
#undef _LZMA_LOC_OPT
|
||||
#include <lzma-sdk/C/7zip/Compress/LZMA_C/LzmaDecode.h>
|
||||
#include <lzma-sdk/C/7zip/Compress/LZMA_C/LzmaDecode.c>
|
||||
|
||||
int upx_lzma_decompress(const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned *dst_len,
|
||||
int method, const upx_compress_result_t *cresult) {
|
||||
assert(M_IS_LZMA(method));
|
||||
// see res->num_probs above
|
||||
COMPILE_TIME_ASSERT(sizeof(CProb) == 2)
|
||||
COMPILE_TIME_ASSERT(LZMA_BASE_SIZE == 1846)
|
||||
COMPILE_TIME_ASSERT(LZMA_LIT_SIZE == 768)
|
||||
|
||||
CLzmaDecoderState s;
|
||||
memset(&s, 0, sizeof(s));
|
||||
SizeT src_out = 0, dst_out = 0;
|
||||
int r = UPX_E_ERROR;
|
||||
int rh;
|
||||
|
||||
// decode UPX-style properties (2 bytes)
|
||||
if (src_len < 3) {
|
||||
r = UPX_E_INPUT_OVERRUN;
|
||||
goto error;
|
||||
}
|
||||
s.Properties.pb = src[0] & 7;
|
||||
s.Properties.lp = (src[1] >> 4);
|
||||
s.Properties.lc = src[1] & 15;
|
||||
if (s.Properties.pb >= 5)
|
||||
goto error;
|
||||
if (s.Properties.lp >= 5)
|
||||
goto error;
|
||||
if (s.Properties.lc >= 9)
|
||||
goto error;
|
||||
// UPX extra stuff in first byte: 5 high bits convenience for stub decompressor
|
||||
if ((src[0] >> 3) != s.Properties.lc + s.Properties.lp)
|
||||
goto error;
|
||||
src += 2;
|
||||
src_len -= 2;
|
||||
|
||||
if (cresult) {
|
||||
assert(cresult->debug.method == method);
|
||||
assert(cresult->result_lzma.pos_bits == (unsigned) s.Properties.pb);
|
||||
assert(cresult->result_lzma.lit_pos_bits == (unsigned) s.Properties.lp);
|
||||
assert(cresult->result_lzma.lit_context_bits == (unsigned) s.Properties.lc);
|
||||
assert(cresult->result_lzma.num_probs == (unsigned) LzmaGetNumProbs(&s.Properties));
|
||||
const lzma_compress_result_t *res = &cresult->result_lzma;
|
||||
// printf("\nlzma_decompress config: %u %u %u %u %u\n", res->pos_bits, res->lit_pos_bits,
|
||||
// res->lit_context_bits, res->dict_size, res->num_probs);
|
||||
UNUSED(res);
|
||||
}
|
||||
s.Probs = (CProb *) malloc(sizeof(CProb) * LzmaGetNumProbs(&s.Properties));
|
||||
if (!s.Probs) {
|
||||
r = UPX_E_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
}
|
||||
rh = LzmaDecode(&s, src, src_len, &src_out, dst, *dst_len, &dst_out);
|
||||
assert(src_out <= src_len);
|
||||
assert(dst_out <= *dst_len);
|
||||
if (rh == 0) {
|
||||
r = UPX_E_OK;
|
||||
if (src_out != src_len)
|
||||
r = UPX_E_INPUT_NOT_CONSUMED;
|
||||
} else if (rh == LZMA_RESULT_INPUT_OVERRUN)
|
||||
r = UPX_E_INPUT_OVERRUN;
|
||||
else if (rh == LZMA_RESULT_OUTPUT_OVERRUN)
|
||||
r = UPX_E_OUTPUT_OVERRUN;
|
||||
|
||||
error:
|
||||
*dst_len = dst_out;
|
||||
free(s.Probs);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
// test_overlap - see <ucl/ucl.h> for semantics
|
||||
**************************************************************************/
|
||||
|
||||
int upx_lzma_test_overlap(const upx_bytep buf, const upx_bytep tbuf, unsigned src_off,
|
||||
unsigned src_len, unsigned *dst_len, int method,
|
||||
const upx_compress_result_t *cresult) {
|
||||
assert(M_IS_LZMA(method));
|
||||
|
||||
MemBuffer b(src_off + src_len);
|
||||
memcpy(b + src_off, buf + src_off, src_len);
|
||||
unsigned saved_dst_len = *dst_len;
|
||||
int r = upx_lzma_decompress(raw_index_bytes(b, src_off, src_len), src_len,
|
||||
raw_bytes(b, *dst_len), dst_len, method, cresult);
|
||||
if (r != UPX_E_OK)
|
||||
return r;
|
||||
if (*dst_len != saved_dst_len)
|
||||
return UPX_E_ERROR;
|
||||
// NOTE: there is a very tiny possibility that decompression has
|
||||
// succeeded but the data is not restored correctly because of
|
||||
// in-place buffer overlapping, so we use an extra memcmp().
|
||||
if (tbuf != nullptr && memcmp(tbuf, b, *dst_len) != 0)
|
||||
return UPX_E_ERROR;
|
||||
return UPX_E_OK;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
// misc
|
||||
**************************************************************************/
|
||||
|
||||
int upx_lzma_init(void) { return 0; }
|
||||
|
||||
const char *upx_lzma_version_string(void) { return "4.43"; }
|
||||
|
||||
/*************************************************************************
|
||||
// doctest checks
|
||||
**************************************************************************/
|
||||
|
||||
TEST_CASE("upx_lzma_decompress") {
|
||||
typedef const upx_byte C;
|
||||
C *c_data;
|
||||
upx_byte d_buf[16];
|
||||
unsigned d_len;
|
||||
int r;
|
||||
|
||||
c_data = (C *) "\x1a\x03\x00\x7f\xed\x3c\x00\x00\x00";
|
||||
d_len = 16;
|
||||
r = upx_lzma_decompress(c_data, 9, d_buf, &d_len, M_LZMA, nullptr);
|
||||
CHECK((r == 0 && d_len == 16));
|
||||
r = upx_lzma_decompress(c_data, 8, d_buf, &d_len, M_LZMA, nullptr);
|
||||
CHECK(r == UPX_E_INPUT_OVERRUN);
|
||||
d_len = 15;
|
||||
r = upx_lzma_decompress(c_data, 9, d_buf, &d_len, M_LZMA, nullptr);
|
||||
CHECK(r == UPX_E_OUTPUT_OVERRUN);
|
||||
}
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -0,0 +1,367 @@
|
||||
/* compress_ucl.cpp --
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
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
|
||||
<markus@oberhumer.com>
|
||||
*/
|
||||
|
||||
#include "../conf.h"
|
||||
#include "compress.h"
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
static int convert_errno_from_ucl(int r) {
|
||||
switch (r) {
|
||||
case UCL_E_OK:
|
||||
return UPX_E_OK;
|
||||
case UCL_E_ERROR:
|
||||
return UPX_E_ERROR;
|
||||
case UCL_E_OUT_OF_MEMORY:
|
||||
return UPX_E_OUT_OF_MEMORY;
|
||||
case UCL_E_NOT_COMPRESSIBLE:
|
||||
return UPX_E_NOT_COMPRESSIBLE;
|
||||
case UCL_E_INPUT_OVERRUN:
|
||||
return UPX_E_INPUT_OVERRUN;
|
||||
case UCL_E_OUTPUT_OVERRUN:
|
||||
return UPX_E_OUTPUT_OVERRUN;
|
||||
case UCL_E_LOOKBEHIND_OVERRUN:
|
||||
return UPX_E_LOOKBEHIND_OVERRUN;
|
||||
case UCL_E_EOF_NOT_FOUND:
|
||||
return UPX_E_EOF_NOT_FOUND;
|
||||
case UCL_E_INPUT_NOT_CONSUMED:
|
||||
return UPX_E_INPUT_NOT_CONSUMED;
|
||||
case UCL_E_INVALID_ARGUMENT:
|
||||
return UPX_E_INVALID_ARGUMENT;
|
||||
// UCL extra:
|
||||
case UCL_E_OVERLAP_OVERRUN:
|
||||
return UPX_E_ERROR;
|
||||
}
|
||||
return UPX_E_ERROR;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
static void __UCL_CDECL wrap_nprogress_ucl(ucl_uint a, ucl_uint b, int state, ucl_voidp user) {
|
||||
if (state != -1 && state != 3)
|
||||
return;
|
||||
upx_callback_p cb = (upx_callback_p) user;
|
||||
if (cb && cb->nprogress)
|
||||
cb->nprogress(cb, a, b);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
int upx_ucl_compress(const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned *dst_len,
|
||||
upx_callback_p cb_parm, int method, int level,
|
||||
const upx_compress_config_t *cconf_parm, upx_compress_result_t *cresult) {
|
||||
int r;
|
||||
assert(level > 0);
|
||||
assert(cresult != nullptr);
|
||||
|
||||
COMPILE_TIME_ASSERT(sizeof(ucl_compress_config_t) == sizeof(REAL_ucl_compress_config_t))
|
||||
|
||||
ucl_progress_callback_t cb;
|
||||
cb.callback = nullptr;
|
||||
cb.user = nullptr;
|
||||
if (cb_parm && cb_parm->nprogress) {
|
||||
cb.callback = wrap_nprogress_ucl;
|
||||
cb.user = cb_parm;
|
||||
}
|
||||
|
||||
ucl_compress_config_t cconf;
|
||||
cconf.reset();
|
||||
if (cconf_parm) {
|
||||
// cconf = cconf_parm->conf_ucl; // struct copy
|
||||
memcpy(&cconf, &cconf_parm->conf_ucl, sizeof(cconf));
|
||||
}
|
||||
|
||||
ucl_uint *const res = cresult->result_ucl.result;
|
||||
// assume no info available - fill in worst case results
|
||||
// res[0] = 1; // min_offset_found - NOT USED
|
||||
res[1] = src_len - 1; // max_offset_found
|
||||
// res[2] = 2; // min_match_found - NOT USED
|
||||
res[3] = src_len - 1; // max_match_found
|
||||
// res[4] = 1; // min_run_found - NOT USED
|
||||
res[5] = src_len; // max_run_found
|
||||
res[6] = 1; // first_offset_found
|
||||
// res[7] = 999999; // same_match_offsets_found - NOT USED
|
||||
|
||||
// prepare bit-buffer settings
|
||||
cconf.bb_endian = 0;
|
||||
cconf.bb_size = 0;
|
||||
if (method >= M_NRV2B_LE32 && method <= M_NRV2E_LE16) {
|
||||
static const unsigned char sizes[3] = {32, 8, 16};
|
||||
cconf.bb_size = sizes[(method - M_NRV2B_LE32) % 3];
|
||||
} else {
|
||||
throwInternalError("unknown compression method");
|
||||
return UPX_E_ERROR;
|
||||
}
|
||||
|
||||
// optimize compression parms
|
||||
if (level <= 3 && cconf.max_offset == UCL_UINT_MAX)
|
||||
cconf.max_offset = 8 * 1024 - 1;
|
||||
else if (level == 4 && cconf.max_offset == UCL_UINT_MAX)
|
||||
cconf.max_offset = 32 * 1024 - 1;
|
||||
|
||||
if M_IS_NRV2B (method)
|
||||
r = ucl_nrv2b_99_compress(src, src_len, dst, dst_len, &cb, level, &cconf, res);
|
||||
else if M_IS_NRV2D (method)
|
||||
r = ucl_nrv2d_99_compress(src, src_len, dst, dst_len, &cb, level, &cconf, res);
|
||||
else if M_IS_NRV2E (method)
|
||||
r = ucl_nrv2e_99_compress(src, src_len, dst, dst_len, &cb, level, &cconf, res);
|
||||
else {
|
||||
throwInternalError("unknown compression method");
|
||||
return UPX_E_ERROR;
|
||||
}
|
||||
|
||||
// make sure first_offset_found is set
|
||||
if (res[6] == 0)
|
||||
res[6] = 1;
|
||||
|
||||
return convert_errno_from_ucl(r);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
int upx_ucl_decompress(const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned *dst_len,
|
||||
int method, const upx_compress_result_t *cresult) {
|
||||
int r;
|
||||
|
||||
switch (method) {
|
||||
case M_NRV2B_8:
|
||||
r = ucl_nrv2b_decompress_safe_8(src, src_len, dst, dst_len, nullptr);
|
||||
break;
|
||||
case M_NRV2B_LE16:
|
||||
r = ucl_nrv2b_decompress_safe_le16(src, src_len, dst, dst_len, nullptr);
|
||||
break;
|
||||
case M_NRV2B_LE32:
|
||||
r = ucl_nrv2b_decompress_safe_le32(src, src_len, dst, dst_len, nullptr);
|
||||
break;
|
||||
case M_NRV2D_8:
|
||||
r = ucl_nrv2d_decompress_safe_8(src, src_len, dst, dst_len, nullptr);
|
||||
break;
|
||||
case M_NRV2D_LE16:
|
||||
r = ucl_nrv2d_decompress_safe_le16(src, src_len, dst, dst_len, nullptr);
|
||||
break;
|
||||
case M_NRV2D_LE32:
|
||||
r = ucl_nrv2d_decompress_safe_le32(src, src_len, dst, dst_len, nullptr);
|
||||
break;
|
||||
case M_NRV2E_8:
|
||||
r = ucl_nrv2e_decompress_safe_8(src, src_len, dst, dst_len, nullptr);
|
||||
break;
|
||||
case M_NRV2E_LE16:
|
||||
r = ucl_nrv2e_decompress_safe_le16(src, src_len, dst, dst_len, nullptr);
|
||||
break;
|
||||
case M_NRV2E_LE32:
|
||||
r = ucl_nrv2e_decompress_safe_le32(src, src_len, dst, dst_len, nullptr);
|
||||
break;
|
||||
default:
|
||||
throwInternalError("unknown decompression method");
|
||||
return UPX_E_ERROR;
|
||||
}
|
||||
|
||||
UNUSED(cresult);
|
||||
return convert_errno_from_ucl(r);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
int upx_ucl_test_overlap(const upx_bytep buf, const upx_bytep tbuf, unsigned src_off,
|
||||
unsigned src_len, unsigned *dst_len, int method,
|
||||
const upx_compress_result_t *cresult) {
|
||||
int r;
|
||||
UNUSED(tbuf); // not needed for UCL
|
||||
|
||||
switch (method) {
|
||||
case M_NRV2B_8:
|
||||
r = ucl_nrv2b_test_overlap_8(buf, src_off, src_len, dst_len, nullptr);
|
||||
break;
|
||||
case M_NRV2B_LE16:
|
||||
r = ucl_nrv2b_test_overlap_le16(buf, src_off, src_len, dst_len, nullptr);
|
||||
break;
|
||||
case M_NRV2B_LE32:
|
||||
r = ucl_nrv2b_test_overlap_le32(buf, src_off, src_len, dst_len, nullptr);
|
||||
break;
|
||||
case M_NRV2D_8:
|
||||
r = ucl_nrv2d_test_overlap_8(buf, src_off, src_len, dst_len, nullptr);
|
||||
break;
|
||||
case M_NRV2D_LE16:
|
||||
r = ucl_nrv2d_test_overlap_le16(buf, src_off, src_len, dst_len, nullptr);
|
||||
break;
|
||||
case M_NRV2D_LE32:
|
||||
r = ucl_nrv2d_test_overlap_le32(buf, src_off, src_len, dst_len, nullptr);
|
||||
break;
|
||||
case M_NRV2E_8:
|
||||
r = ucl_nrv2e_test_overlap_8(buf, src_off, src_len, dst_len, nullptr);
|
||||
break;
|
||||
case M_NRV2E_LE16:
|
||||
r = ucl_nrv2e_test_overlap_le16(buf, src_off, src_len, dst_len, nullptr);
|
||||
break;
|
||||
case M_NRV2E_LE32:
|
||||
r = ucl_nrv2e_test_overlap_le32(buf, src_off, src_len, dst_len, nullptr);
|
||||
break;
|
||||
default:
|
||||
throwInternalError("unknown decompression method");
|
||||
return UPX_E_ERROR;
|
||||
}
|
||||
|
||||
UNUSED(cresult);
|
||||
return convert_errno_from_ucl(r);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
// misc
|
||||
**************************************************************************/
|
||||
|
||||
extern "C" {
|
||||
static ucl_voidp __UCL_CDECL my_malloc(ucl_uint n) { return calloc(1, n); }
|
||||
static void __UCL_CDECL my_free(ucl_voidp p) { free(p); }
|
||||
}
|
||||
|
||||
int upx_ucl_init(void) {
|
||||
if (ucl_init() != UCL_E_OK)
|
||||
return -1;
|
||||
if (UCL_VERSION != ucl_version() || strcmp(UCL_VERSION_STRING, ucl_version_string()) != 0)
|
||||
return -2;
|
||||
ucl_set_malloc_hooks(my_malloc, my_free);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *upx_ucl_version_string(void) { return ucl_version_string(); }
|
||||
|
||||
unsigned upx_ucl_adler32(const void *buf, unsigned len, unsigned adler) {
|
||||
return ucl_adler32(adler, (const ucl_bytep) buf, len);
|
||||
}
|
||||
|
||||
#if 0 // UNUSED
|
||||
unsigned upx_ucl_crc32(const void *buf, unsigned len, unsigned crc) {
|
||||
return ucl_crc32(crc, (const ucl_bytep) buf, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
// doctest checks
|
||||
**************************************************************************/
|
||||
|
||||
#if DEBUG && !defined(DOCTEST_CONFIG_DISABLE) && 1
|
||||
|
||||
#include "../util/membuffer.h"
|
||||
|
||||
static bool check_ucl(const int method, const unsigned expected_c_len) {
|
||||
const unsigned u_len = 16384;
|
||||
const unsigned c_extra = 4096;
|
||||
MemBuffer u_buf, c_buf, d_buf;
|
||||
unsigned c_len, d_len;
|
||||
upx_compress_result_t cresult;
|
||||
int r;
|
||||
const int level = 3; // don't waste time
|
||||
|
||||
u_buf.alloc(u_len);
|
||||
memset(u_buf, 0, u_len);
|
||||
c_buf.allocForCompression(u_len, c_extra);
|
||||
d_buf.allocForDecompression(u_len);
|
||||
|
||||
c_len = c_buf.getSize() - c_extra;
|
||||
r = upx_ucl_compress(raw_bytes(u_buf, u_len), u_len, raw_index_bytes(c_buf, c_extra, c_len),
|
||||
&c_len, nullptr, method, level, NULL_cconf, &cresult);
|
||||
if (r != 0 || c_len != expected_c_len)
|
||||
return false;
|
||||
|
||||
d_len = d_buf.getSize();
|
||||
r = upx_ucl_decompress(raw_index_bytes(c_buf, c_extra, c_len), c_len, raw_bytes(d_buf, d_len),
|
||||
&d_len, method, nullptr);
|
||||
if (r != 0 || d_len != u_len || memcmp(u_buf, d_buf, u_len) != 0)
|
||||
return false;
|
||||
|
||||
d_len = u_len - 1;
|
||||
r = upx_ucl_decompress(raw_index_bytes(c_buf, c_extra, c_len), c_len, raw_bytes(d_buf, d_len),
|
||||
&d_len, method, nullptr);
|
||||
if (r == 0)
|
||||
return false;
|
||||
|
||||
// TODO: rewrite Packer::findOverlapOverhead() so that we can test it here
|
||||
// unsigned x_len = d_len;
|
||||
// r = upx_ucl_test_overlap(c_buf, u_buf, c_extra, c_len, &x_len, method, nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST_CASE("compress_ucl") {
|
||||
CHECK(check_ucl(M_NRV2B_8, 34));
|
||||
CHECK(check_ucl(M_NRV2B_LE16, 34));
|
||||
CHECK(check_ucl(M_NRV2B_LE32, 34));
|
||||
CHECK(check_ucl(M_NRV2D_8, 32));
|
||||
CHECK(check_ucl(M_NRV2D_LE16, 32));
|
||||
CHECK(check_ucl(M_NRV2D_LE32, 34));
|
||||
CHECK(check_ucl(M_NRV2E_8, 32));
|
||||
CHECK(check_ucl(M_NRV2E_LE16, 32));
|
||||
CHECK(check_ucl(M_NRV2E_LE32, 34));
|
||||
}
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
TEST_CASE("upx_ucl_decompress") {
|
||||
typedef const upx_byte C;
|
||||
C *c_data;
|
||||
upx_byte d_buf[16];
|
||||
unsigned d_len;
|
||||
int r;
|
||||
|
||||
c_data = (C *) "\x92\xff\x10\x00\x00\x00\x00\x00\x48\xff";
|
||||
d_len = 16;
|
||||
r = upx_ucl_decompress(c_data, 10, d_buf, &d_len, M_NRV2B_8, nullptr);
|
||||
CHECK((r == 0 && d_len == 16));
|
||||
r = upx_ucl_decompress(c_data, 9, d_buf, &d_len, M_NRV2B_8, nullptr);
|
||||
CHECK(r == UPX_E_INPUT_OVERRUN);
|
||||
d_len = 15;
|
||||
r = upx_ucl_decompress(c_data, 10, d_buf, &d_len, M_NRV2B_8, nullptr);
|
||||
CHECK(r == UPX_E_OUTPUT_OVERRUN);
|
||||
|
||||
c_data = (C *) "\x92\xff\x10\x92\x49\x24\x92\xa0\xff";
|
||||
d_len = 16;
|
||||
r = upx_ucl_decompress(c_data, 9, d_buf, &d_len, M_NRV2D_8, nullptr);
|
||||
CHECK((r == 0 && d_len == 16));
|
||||
r = upx_ucl_decompress(c_data, 8, d_buf, &d_len, M_NRV2D_8, nullptr);
|
||||
CHECK(r == UPX_E_INPUT_OVERRUN);
|
||||
d_len = 15;
|
||||
r = upx_ucl_decompress(c_data, 9, d_buf, &d_len, M_NRV2D_8, nullptr);
|
||||
CHECK(r == UPX_E_OUTPUT_OVERRUN);
|
||||
|
||||
c_data = (C *) "\x90\xff\xb0\x92\x49\x24\x92\xa0\xff";
|
||||
d_len = 16;
|
||||
r = upx_ucl_decompress(c_data, 9, d_buf, &d_len, M_NRV2E_8, nullptr);
|
||||
CHECK((r == 0 && d_len == 16));
|
||||
r = upx_ucl_decompress(c_data, 8, d_buf, &d_len, M_NRV2E_8, nullptr);
|
||||
CHECK(r == UPX_E_INPUT_OVERRUN);
|
||||
d_len = 15;
|
||||
r = upx_ucl_decompress(c_data, 9, d_buf, &d_len, M_NRV2E_8, nullptr);
|
||||
CHECK(r == UPX_E_OUTPUT_OVERRUN);
|
||||
}
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -0,0 +1,307 @@
|
||||
/* compress_zlib.cpp --
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
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
|
||||
<markus@oberhumer.com>
|
||||
*/
|
||||
|
||||
#include "../conf.h"
|
||||
#include "compress.h"
|
||||
#include "../util/membuffer.h"
|
||||
#include <zlib/zlib.h>
|
||||
#include <zlib/deflate.h>
|
||||
|
||||
void zlib_compress_config_t::reset() {
|
||||
mem_clear(this, sizeof(*this));
|
||||
|
||||
mem_level.reset();
|
||||
window_bits.reset();
|
||||
strategy.reset();
|
||||
}
|
||||
|
||||
static int convert_errno_from_zlib(int zr) {
|
||||
switch (zr) {
|
||||
case Z_OK:
|
||||
return UPX_E_OK;
|
||||
// positive values
|
||||
case Z_STREAM_END:
|
||||
return UPX_E_ERROR;
|
||||
case Z_NEED_DICT:
|
||||
return UPX_E_ERROR;
|
||||
// negative values
|
||||
case Z_ERRNO:
|
||||
return UPX_E_ERROR;
|
||||
case Z_STREAM_ERROR:
|
||||
return UPX_E_ERROR;
|
||||
case Z_DATA_ERROR:
|
||||
return UPX_E_ERROR;
|
||||
case Z_MEM_ERROR:
|
||||
return UPX_E_OUT_OF_MEMORY;
|
||||
case Z_BUF_ERROR:
|
||||
return UPX_E_OUTPUT_OVERRUN;
|
||||
case Z_VERSION_ERROR:
|
||||
return UPX_E_ERROR;
|
||||
case -7: // UPX extra
|
||||
return UPX_E_INPUT_OVERRUN;
|
||||
}
|
||||
return UPX_E_ERROR;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
int upx_zlib_compress(const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned *dst_len,
|
||||
upx_callback_p cb_parm, int method, int level,
|
||||
const upx_compress_config_t *cconf_parm, upx_compress_result_t *cresult) {
|
||||
assert(method == M_DEFLATE);
|
||||
assert(level > 0);
|
||||
assert(cresult != nullptr);
|
||||
UNUSED(cb_parm);
|
||||
int r = UPX_E_ERROR;
|
||||
int zr;
|
||||
const zlib_compress_config_t *const lcconf = cconf_parm ? &cconf_parm->conf_zlib : nullptr;
|
||||
zlib_compress_result_t *const res = &cresult->result_zlib;
|
||||
|
||||
if (level == 10)
|
||||
level = 9;
|
||||
|
||||
zlib_compress_config_t::mem_level_t mem_level;
|
||||
zlib_compress_config_t::window_bits_t window_bits;
|
||||
zlib_compress_config_t::strategy_t strategy;
|
||||
// cconf overrides
|
||||
if (lcconf) {
|
||||
oassign(mem_level, lcconf->mem_level);
|
||||
oassign(window_bits, lcconf->window_bits);
|
||||
oassign(strategy, lcconf->strategy);
|
||||
}
|
||||
|
||||
res->dummy = 0;
|
||||
|
||||
z_stream s;
|
||||
s.zalloc = (alloc_func) nullptr;
|
||||
s.zfree = (free_func) nullptr;
|
||||
s.next_in = ACC_UNCONST_CAST(upx_bytep, src);
|
||||
s.avail_in = src_len;
|
||||
s.next_out = dst;
|
||||
s.avail_out = *dst_len;
|
||||
s.total_in = s.total_out = 0;
|
||||
|
||||
zr = (int) deflateInit2(&s, level, Z_DEFLATED, 0 - (int) window_bits, mem_level, strategy);
|
||||
if (zr != Z_OK)
|
||||
goto error;
|
||||
assert(s.state->level == level);
|
||||
zr = deflate(&s, Z_FINISH);
|
||||
if (zr != Z_STREAM_END)
|
||||
goto error;
|
||||
zr = deflateEnd(&s);
|
||||
if (zr != Z_OK)
|
||||
goto error;
|
||||
r = UPX_E_OK;
|
||||
goto done;
|
||||
error:
|
||||
(void) deflateEnd(&s);
|
||||
r = convert_errno_from_zlib(zr);
|
||||
if (r == UPX_E_OK)
|
||||
r = UPX_E_ERROR;
|
||||
done:
|
||||
if (r == UPX_E_OK) {
|
||||
if (s.avail_in != 0 || s.total_in != src_len)
|
||||
r = UPX_E_ERROR;
|
||||
}
|
||||
assert(s.total_in <= src_len);
|
||||
assert(s.total_out <= *dst_len);
|
||||
*dst_len = s.total_out;
|
||||
return r;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
int upx_zlib_decompress(const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned *dst_len,
|
||||
int method, const upx_compress_result_t *cresult) {
|
||||
assert(method == M_DEFLATE);
|
||||
UNUSED(method);
|
||||
UNUSED(cresult);
|
||||
int r = UPX_E_ERROR;
|
||||
int zr;
|
||||
|
||||
z_stream s;
|
||||
s.zalloc = (alloc_func) nullptr;
|
||||
s.zfree = (free_func) nullptr;
|
||||
s.next_in = ACC_UNCONST_CAST(upx_bytep, src);
|
||||
s.avail_in = src_len;
|
||||
s.next_out = dst;
|
||||
s.avail_out = *dst_len;
|
||||
s.total_in = s.total_out = 0;
|
||||
|
||||
zr = inflateInit2(&s, -15);
|
||||
if (zr != Z_OK)
|
||||
goto error;
|
||||
zr = inflate(&s, Z_FINISH);
|
||||
if (zr != Z_STREAM_END) {
|
||||
if (zr == Z_BUF_ERROR && s.avail_in == 0)
|
||||
zr = -7; // UPX extra
|
||||
goto error;
|
||||
}
|
||||
zr = inflateEnd(&s);
|
||||
if (zr != Z_OK)
|
||||
goto error;
|
||||
r = UPX_E_OK;
|
||||
goto done;
|
||||
error:
|
||||
(void) inflateEnd(&s);
|
||||
r = convert_errno_from_zlib(zr);
|
||||
if (r == UPX_E_OK)
|
||||
r = UPX_E_ERROR;
|
||||
done:
|
||||
if (r == UPX_E_OK) {
|
||||
if (s.avail_in != 0 || s.total_in != src_len)
|
||||
r = UPX_E_INPUT_NOT_CONSUMED;
|
||||
}
|
||||
assert(s.total_in <= src_len);
|
||||
assert(s.total_out <= *dst_len);
|
||||
*dst_len = s.total_out;
|
||||
return r;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
// test_overlap - see <ucl/ucl.h> for semantics
|
||||
**************************************************************************/
|
||||
|
||||
int upx_zlib_test_overlap(const upx_bytep buf, const upx_bytep tbuf, unsigned src_off,
|
||||
unsigned src_len, unsigned *dst_len, int method,
|
||||
const upx_compress_result_t *cresult) {
|
||||
assert(method == M_DEFLATE);
|
||||
|
||||
MemBuffer b(src_off + src_len);
|
||||
memcpy(b + src_off, buf + src_off, src_len);
|
||||
unsigned saved_dst_len = *dst_len;
|
||||
int r = upx_zlib_decompress(raw_index_bytes(b, src_off, src_len), src_len,
|
||||
raw_bytes(b, *dst_len), dst_len, method, cresult);
|
||||
if (r != UPX_E_OK)
|
||||
return r;
|
||||
if (*dst_len != saved_dst_len)
|
||||
return UPX_E_ERROR;
|
||||
// NOTE: there is a very tiny possibility that decompression has
|
||||
// succeeded but the data is not restored correctly because of
|
||||
// in-place buffer overlapping, so we use an extra memcmp().
|
||||
if (tbuf != nullptr && memcmp(tbuf, b, *dst_len) != 0)
|
||||
return UPX_E_ERROR;
|
||||
return UPX_E_OK;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
// misc
|
||||
**************************************************************************/
|
||||
|
||||
int upx_zlib_init(void) {
|
||||
if (strcmp(ZLIB_VERSION, zlibVersion()) != 0)
|
||||
return -2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *upx_zlib_version_string(void) { return zlibVersion(); }
|
||||
|
||||
#if 0 // UNUSED
|
||||
unsigned upx_zlib_adler32(const void *buf, unsigned len, unsigned adler) {
|
||||
return adler32(adler, (const Bytef *) buf, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0 // UNUSED
|
||||
unsigned upx_zlib_crc32(const void *buf, unsigned len, unsigned crc) {
|
||||
return crc32(crc, (const Bytef *) buf, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
// doctest checks
|
||||
**************************************************************************/
|
||||
|
||||
#if DEBUG && !defined(DOCTEST_CONFIG_DISABLE) && 1
|
||||
|
||||
static bool check_zlib(const int method, const int level, const unsigned expected_c_len) {
|
||||
const unsigned u_len = 16384;
|
||||
const unsigned c_extra = 4096;
|
||||
MemBuffer u_buf, c_buf, d_buf;
|
||||
unsigned c_len, d_len;
|
||||
upx_compress_result_t cresult;
|
||||
int r;
|
||||
|
||||
u_buf.alloc(u_len);
|
||||
memset(u_buf, 0, u_len);
|
||||
c_buf.allocForCompression(u_len, c_extra);
|
||||
d_buf.allocForDecompression(u_len);
|
||||
|
||||
c_len = c_buf.getSize() - c_extra;
|
||||
r = upx_zlib_compress(raw_bytes(u_buf, u_len), u_len, raw_index_bytes(c_buf, c_extra, c_len),
|
||||
&c_len, nullptr, method, level, NULL_cconf, &cresult);
|
||||
if (r != 0 || c_len != expected_c_len)
|
||||
return false;
|
||||
|
||||
d_len = d_buf.getSize();
|
||||
r = upx_zlib_decompress(raw_index_bytes(c_buf, c_extra, c_len), c_len, raw_bytes(d_buf, d_len),
|
||||
&d_len, method, nullptr);
|
||||
if (r != 0 || d_len != u_len || memcmp(u_buf, d_buf, u_len) != 0)
|
||||
return false;
|
||||
|
||||
d_len = u_len - 1;
|
||||
r = upx_zlib_decompress(raw_index_bytes(c_buf, c_extra, c_len), c_len, raw_bytes(d_buf, d_len),
|
||||
&d_len, method, nullptr);
|
||||
if (r == 0)
|
||||
return false;
|
||||
|
||||
// TODO: rewrite Packer::findOverlapOverhead() so that we can test it here
|
||||
// unsigned x_len = d_len;
|
||||
// r = upx_zlib_test_overlap(c_buf, u_buf, c_extra, c_len, &x_len, method, nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST_CASE("compress_zlib") {
|
||||
CHECK(check_zlib(M_DEFLATE, 1, 89));
|
||||
CHECK(check_zlib(M_DEFLATE, 3, 89));
|
||||
CHECK(check_zlib(M_DEFLATE, 5, 33));
|
||||
}
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
TEST_CASE("upx_zlib_decompress") {
|
||||
typedef const upx_byte C;
|
||||
C *c_data;
|
||||
upx_byte d_buf[16];
|
||||
unsigned d_len;
|
||||
int r;
|
||||
|
||||
c_data = (C *) "\xfb\xff\x1f\x15\x00\x00";
|
||||
d_len = 16;
|
||||
r = upx_zlib_decompress(c_data, 6, d_buf, &d_len, M_DEFLATE, nullptr);
|
||||
CHECK((r == 0 && d_len == 16));
|
||||
r = upx_zlib_decompress(c_data, 5, d_buf, &d_len, M_DEFLATE, nullptr);
|
||||
CHECK(r == UPX_E_INPUT_OVERRUN);
|
||||
d_len = 15;
|
||||
r = upx_zlib_decompress(c_data, 6, d_buf, &d_len, M_DEFLATE, nullptr);
|
||||
CHECK(r == UPX_E_OUTPUT_OVERRUN);
|
||||
}
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -0,0 +1,229 @@
|
||||
/* compress_zstd.cpp --
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
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
|
||||
<markus@oberhumer.com>
|
||||
*/
|
||||
|
||||
#include "../conf.h"
|
||||
|
||||
void zstd_compress_config_t::reset() { mem_clear(this, sizeof(*this)); }
|
||||
|
||||
#if WITH_ZSTD
|
||||
#include "compress.h"
|
||||
#include "../util/membuffer.h"
|
||||
#include <zstd/lib/zstd.h>
|
||||
#include <zstd/lib/zstd_errors.h>
|
||||
#include <zstd/lib/compress/hist.h>
|
||||
|
||||
static int convert_errno_from_zstd(size_t zr) {
|
||||
const ZSTD_ErrorCode ze = ZSTD_getErrorCode(zr);
|
||||
switch (ze) {
|
||||
case ZSTD_error_memory_allocation:
|
||||
return UPX_E_OUT_OF_MEMORY;
|
||||
case ZSTD_error_srcSize_wrong:
|
||||
return UPX_E_INPUT_OVERRUN;
|
||||
case ZSTD_error_dstSize_tooSmall:
|
||||
return UPX_E_OUTPUT_OVERRUN;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return UPX_E_ERROR;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
// TODO later: use advanced compression API for compression finetuning
|
||||
**************************************************************************/
|
||||
|
||||
int upx_zstd_compress(const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned *dst_len,
|
||||
upx_callback_p cb_parm, int method, int level,
|
||||
const upx_compress_config_t *cconf_parm, upx_compress_result_t *cresult) {
|
||||
assert(method == M_ZSTD);
|
||||
assert(level > 0);
|
||||
assert(cresult != nullptr);
|
||||
UNUSED(cb_parm);
|
||||
int r = UPX_E_ERROR;
|
||||
size_t zr;
|
||||
const zstd_compress_config_t *const lcconf = cconf_parm ? &cconf_parm->conf_zstd : nullptr;
|
||||
zstd_compress_result_t *const res = &cresult->result_zstd;
|
||||
|
||||
// TODO later: map level 1..10 to zstd-level 1..22
|
||||
if (level == 10)
|
||||
level = 22;
|
||||
|
||||
// cconf overrides
|
||||
if (lcconf) {
|
||||
UNUSED(lcconf);
|
||||
}
|
||||
|
||||
res->dummy = 0;
|
||||
|
||||
zr = ZSTD_compress(dst, *dst_len, src, src_len, level);
|
||||
if (ZSTD_isError(zr)) {
|
||||
*dst_len = 0; // TODO ???
|
||||
r = convert_errno_from_zstd(zr);
|
||||
assert(r != UPX_E_OK);
|
||||
} else {
|
||||
assert(zr <= *dst_len);
|
||||
*dst_len = (unsigned) zr;
|
||||
r = UPX_E_OK;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
int upx_zstd_decompress(const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned *dst_len,
|
||||
int method, const upx_compress_result_t *cresult) {
|
||||
assert(method == M_ZSTD);
|
||||
UNUSED(method);
|
||||
UNUSED(cresult);
|
||||
int r = UPX_E_ERROR;
|
||||
size_t zr;
|
||||
|
||||
zr = ZSTD_decompress(dst, *dst_len, src, src_len);
|
||||
if (ZSTD_isError(zr)) {
|
||||
*dst_len = 0; // TODO ???
|
||||
r = convert_errno_from_zstd(zr);
|
||||
assert(r != UPX_E_OK);
|
||||
} else {
|
||||
assert(zr <= *dst_len);
|
||||
*dst_len = (unsigned) zr;
|
||||
r = UPX_E_OK;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
// test_overlap - see <ucl/ucl.h> for semantics
|
||||
**************************************************************************/
|
||||
|
||||
int upx_zstd_test_overlap(const upx_bytep buf, const upx_bytep tbuf, unsigned src_off,
|
||||
unsigned src_len, unsigned *dst_len, int method,
|
||||
const upx_compress_result_t *cresult) {
|
||||
assert(method == M_ZSTD);
|
||||
|
||||
MemBuffer b(src_off + src_len);
|
||||
memcpy(b + src_off, buf + src_off, src_len);
|
||||
unsigned saved_dst_len = *dst_len;
|
||||
int r = upx_zstd_decompress(raw_index_bytes(b, src_off, src_len), src_len,
|
||||
raw_bytes(b, *dst_len), dst_len, method, cresult);
|
||||
if (r != UPX_E_OK)
|
||||
return r;
|
||||
if (*dst_len != saved_dst_len)
|
||||
return UPX_E_ERROR;
|
||||
// NOTE: there is a very tiny possibility that decompression has
|
||||
// succeeded but the data is not restored correctly because of
|
||||
// in-place buffer overlapping, so we use an extra memcmp().
|
||||
if (tbuf != nullptr && memcmp(tbuf, b, *dst_len) != 0)
|
||||
return UPX_E_ERROR;
|
||||
return UPX_E_OK;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
// misc
|
||||
**************************************************************************/
|
||||
|
||||
int upx_zstd_init(void) {
|
||||
if (strcmp(ZSTD_VERSION_STRING, ZSTD_versionString()) != 0)
|
||||
return -2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *upx_zstd_version_string(void) { return ZSTD_VERSION_STRING; }
|
||||
|
||||
/*************************************************************************
|
||||
// doctest checks
|
||||
**************************************************************************/
|
||||
|
||||
#if DEBUG && !defined(DOCTEST_CONFIG_DISABLE) && 1
|
||||
|
||||
static bool check_zstd(const int method, const int level, const unsigned expected_c_len) {
|
||||
const unsigned u_len = 16384;
|
||||
const unsigned c_extra = 4096;
|
||||
MemBuffer u_buf, c_buf, d_buf;
|
||||
unsigned c_len, d_len;
|
||||
upx_compress_result_t cresult;
|
||||
int r;
|
||||
|
||||
u_buf.alloc(u_len);
|
||||
memset(u_buf, 0, u_len);
|
||||
c_buf.allocForCompression(u_len, c_extra);
|
||||
d_buf.allocForDecompression(u_len);
|
||||
|
||||
c_len = c_buf.getSize() - c_extra;
|
||||
r = upx_zstd_compress(raw_bytes(u_buf, u_len), u_len, raw_index_bytes(c_buf, c_extra, c_len),
|
||||
&c_len, nullptr, method, level, NULL_cconf, &cresult);
|
||||
if (r != 0 || c_len != expected_c_len)
|
||||
return false;
|
||||
|
||||
d_len = d_buf.getSize();
|
||||
r = upx_zstd_decompress(raw_index_bytes(c_buf, c_extra, c_len), c_len, raw_bytes(d_buf, d_len),
|
||||
&d_len, method, nullptr);
|
||||
if (r != 0 || d_len != u_len || memcmp(u_buf, d_buf, u_len) != 0)
|
||||
return false;
|
||||
|
||||
d_len = u_len - 1;
|
||||
r = upx_zstd_decompress(raw_index_bytes(c_buf, c_extra, c_len), c_len, raw_bytes(d_buf, d_len),
|
||||
&d_len, method, nullptr);
|
||||
if (r == 0)
|
||||
return false;
|
||||
|
||||
// TODO: rewrite Packer::findOverlapOverhead() so that we can test it here
|
||||
// unsigned x_len = d_len;
|
||||
// r = upx_zstd_test_overlap(c_buf, u_buf, c_extra, c_len, &x_len, method, nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST_CASE("compress_zstd") {
|
||||
CHECK(check_zstd(M_ZSTD, 1, 19));
|
||||
CHECK(check_zstd(M_ZSTD, 3, 19));
|
||||
CHECK(check_zstd(M_ZSTD, 5, 19));
|
||||
}
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
TEST_CASE("upx_zstd_decompress") {
|
||||
typedef const upx_byte C;
|
||||
C *c_data;
|
||||
upx_byte d_buf[32];
|
||||
unsigned d_len;
|
||||
int r;
|
||||
|
||||
c_data = (C *) "\x28\xb5\x2f\xfd\x20\x20\x3d\x00\x00\x08\xff\x01\x00\x34\x4e\x08";
|
||||
d_len = 32;
|
||||
r = upx_zstd_decompress(c_data, 16, d_buf, &d_len, M_ZSTD, nullptr);
|
||||
CHECK((r == 0 && d_len == 32));
|
||||
r = upx_zstd_decompress(c_data, 15, d_buf, &d_len, M_ZSTD, nullptr);
|
||||
CHECK(r == UPX_E_INPUT_OVERRUN);
|
||||
d_len = 31;
|
||||
r = upx_zstd_decompress(c_data, 16, d_buf, &d_len, M_ZSTD, nullptr);
|
||||
CHECK(r == UPX_E_OUTPUT_OVERRUN);
|
||||
}
|
||||
|
||||
#endif // WITH_ZSTD
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -1,565 +0,0 @@
|
||||
/* compress_lzma.cpp --
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 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@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
#include "compress.h"
|
||||
#include "mem.h"
|
||||
|
||||
|
||||
void lzma_compress_config_t::reset()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
|
||||
pos_bits.reset();
|
||||
lit_pos_bits.reset();
|
||||
lit_context_bits.reset();
|
||||
dict_size.reset();
|
||||
fast_mode = 2;
|
||||
num_fast_bytes.reset();
|
||||
match_finder_cycles = 0;
|
||||
|
||||
max_num_probs = 0;
|
||||
}
|
||||
|
||||
|
||||
#if !defined(WITH_LZMA)
|
||||
extern int compress_lzma_dummy;
|
||||
int compress_lzma_dummy = 0;
|
||||
#else
|
||||
|
||||
|
||||
// INFO: the LZMA SDK is covered by a permissive license which allows
|
||||
// using unmodified LZMA source code in UPX and the UPX stubs.
|
||||
// See SPECIAL EXCEPTION below.
|
||||
//
|
||||
// Quoting from lzma-4.43/lzma.txt:
|
||||
//
|
||||
// LICENSE
|
||||
// -------
|
||||
//
|
||||
// LZMA SDK is available under any of the following licenses:
|
||||
//
|
||||
// 1) GNU Lesser General Public License (GNU LGPL)
|
||||
// 2) Common Public License (CPL)
|
||||
// 3) Simplified license for unmodified code (read SPECIAL EXCEPTION)
|
||||
// 4) Proprietary license
|
||||
//
|
||||
// It means that you can select one of these four options and follow rules
|
||||
// of that license.
|
||||
//
|
||||
// 1,2) GNU LGPL and CPL licenses are pretty similar and both these
|
||||
// licenses are classified as
|
||||
// - "Free software licenses" at http://www.gnu.org/
|
||||
// - "OSI-approved" at http://www.opensource.org/
|
||||
//
|
||||
// 3) SPECIAL EXCEPTION
|
||||
//
|
||||
// Igor Pavlov, as the author of this code, expressly permits you
|
||||
// to statically or dynamically link your code (or bind by name)
|
||||
// to the files from LZMA SDK without subjecting your linked
|
||||
// code to the terms of the CPL or GNU LGPL.
|
||||
// Any modifications or additions to files from LZMA SDK, however,
|
||||
// are subject to the GNU LGPL or CPL terms.
|
||||
//
|
||||
// SPECIAL EXCEPTION allows you to use LZMA SDK in applications with closed code,
|
||||
// while you keep LZMA SDK code unmodified.
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// cruft because of pseudo-COM layer
|
||||
**************************************************************************/
|
||||
|
||||
#undef USE_LZMA_PROPERTIES
|
||||
|
||||
#undef MSDOS
|
||||
#undef OS2
|
||||
#undef _WIN32
|
||||
#undef _WIN32_WCE
|
||||
#undef COMPRESS_MF_MT
|
||||
#undef _NO_EXCEPTIONS
|
||||
#if (WITH_LZMA >= 0x449)
|
||||
# define INITGUID 1
|
||||
//# include "CPP/7zip/Compress/LZMA/LZMADecoder.h"
|
||||
# include "CPP/7zip/Compress/LZMA/LZMAEncoder.h"
|
||||
#else
|
||||
# include "C/Common/MyInitGuid.h"
|
||||
//# include "C/7zip/Compress/LZMA/LZMADecoder.h"
|
||||
# include "C/7zip/Compress/LZMA/LZMAEncoder.h"
|
||||
#endif
|
||||
|
||||
namespace MyLzma {
|
||||
|
||||
struct InStream: public ISequentialInStream, public CMyUnknownImp
|
||||
{
|
||||
MY_UNKNOWN_IMP
|
||||
const Byte *b_buf; size_t b_size; size_t b_pos;
|
||||
void Init(const Byte *data, size_t size) {
|
||||
b_buf = data; b_size = size; b_pos = 0;
|
||||
}
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
STDMETHODIMP InStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
size_t remain = b_size - b_pos;
|
||||
if (size > remain) size = (UInt32) remain;
|
||||
memcpy(data, b_buf + b_pos, size);
|
||||
b_pos += size;
|
||||
if (processedSize != NULL) *processedSize = size;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
struct OutStream : public ISequentialOutStream, public CMyUnknownImp
|
||||
{
|
||||
MY_UNKNOWN_IMP
|
||||
Byte *b_buf; size_t b_size; size_t b_pos; bool overflow;
|
||||
void Init(Byte *data, size_t size) {
|
||||
b_buf = data; b_size = size; b_pos = 0; overflow = false;
|
||||
}
|
||||
HRESULT WriteByte(Byte c) {
|
||||
if (b_pos >= b_size) { overflow = true; return E_FAIL; }
|
||||
b_buf[b_pos++] = c;
|
||||
return S_OK;
|
||||
}
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
STDMETHODIMP OutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
size_t remain = b_size - b_pos;
|
||||
if (size > remain) size = (UInt32) remain, overflow = true;
|
||||
memcpy(b_buf + b_pos, data, size);
|
||||
b_pos += size;
|
||||
if (processedSize != NULL) *processedSize = size;
|
||||
return overflow ? E_FAIL : S_OK;
|
||||
}
|
||||
|
||||
struct ProgressInfo : public ICompressProgressInfo, public CMyUnknownImp
|
||||
{
|
||||
MY_UNKNOWN_IMP
|
||||
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
|
||||
upx_callback_p cb;
|
||||
};
|
||||
|
||||
STDMETHODIMP ProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
|
||||
{
|
||||
if (cb && cb->nprogress)
|
||||
cb->nprogress(cb, (unsigned) *inSize, (unsigned) *outSize);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
#if (ACC_CC_INTELC) && defined(__linux__)
|
||||
# pragma warning(disable: 424) // #424: extra ";" ignored
|
||||
#endif
|
||||
|
||||
#if (WITH_LZMA >= 0x449)
|
||||
# include "C/Alloc.c"
|
||||
# include "C/7zCrc.c"
|
||||
# include "C/Compress/Lz/MatchFinder.c"
|
||||
//# include "CPP/7zip/Common/InBuffer.cpp"
|
||||
# include "CPP/7zip/Common/OutBuffer.cpp"
|
||||
# include "CPP/7zip/Common/StreamUtils.cpp"
|
||||
//# include "CPP/7zip/Compress/LZ/LZOutWindow.cpp"
|
||||
//# include "CPP/7zip/Compress/LZMA/LZMADecoder.cpp"
|
||||
# include "CPP/7zip/Compress/LZMA/LZMAEncoder.cpp"
|
||||
# include "CPP/7zip/Compress/RangeCoder/RangeCoderBit.cpp"
|
||||
#else
|
||||
# include "C/Common/Alloc.cpp"
|
||||
# include "C/Common/CRC.cpp"
|
||||
//# include "C/7zip/Common/InBuffer.cpp"
|
||||
# include "C/7zip/Common/OutBuffer.cpp"
|
||||
# include "C/7zip/Common/StreamUtils.cpp"
|
||||
# include "C/7zip/Compress/LZ/LZInWindow.cpp"
|
||||
//# include "C/7zip/Compress/LZ/LZOutWindow.cpp"
|
||||
//# include "C/7zip/Compress/LZMA/LZMADecoder.cpp"
|
||||
# include "C/7zip/Compress/LZMA/LZMAEncoder.cpp"
|
||||
# include "C/7zip/Compress/RangeCoder/RangeCoderBit.cpp"
|
||||
#endif
|
||||
#undef RC_NORMALIZE
|
||||
|
||||
|
||||
int upx_lzma_compress ( const upx_bytep src, unsigned src_len,
|
||||
upx_bytep dst, unsigned* dst_len,
|
||||
upx_callback_p cb,
|
||||
int method, int level,
|
||||
const upx_compress_config_t *cconf_parm,
|
||||
upx_compress_result_t *cresult )
|
||||
{
|
||||
assert(M_IS_LZMA(method));
|
||||
assert(level > 0); assert(cresult != NULL);
|
||||
|
||||
int r = UPX_E_ERROR;
|
||||
HRESULT rh;
|
||||
const lzma_compress_config_t *lcconf = cconf_parm ? &cconf_parm->conf_lzma : NULL;
|
||||
lzma_compress_result_t *res = &cresult->result_lzma;
|
||||
|
||||
MyLzma::InStream is; is.AddRef();
|
||||
MyLzma::OutStream os; os.AddRef();
|
||||
is.Init(src, src_len);
|
||||
os.Init(dst, *dst_len);
|
||||
|
||||
MyLzma::ProgressInfo progress; progress.AddRef();
|
||||
progress.cb = cb;
|
||||
|
||||
NCompress::NLZMA::CEncoder enc;
|
||||
const PROPID propIDs[8] = {
|
||||
NCoderPropID::kPosStateBits, // 0 pb _posStateBits(2)
|
||||
NCoderPropID::kLitPosBits, // 1 lp _numLiteralPosStateBits(0)
|
||||
NCoderPropID::kLitContextBits, // 2 lc _numLiteralContextBits(3)
|
||||
NCoderPropID::kDictionarySize, // 3 ds
|
||||
NCoderPropID::kAlgorithm, // 4 fm _fastmode
|
||||
NCoderPropID::kNumFastBytes, // 5 fb
|
||||
NCoderPropID::kMatchFinderCycles, // 6 mfc _matchFinderCycles, _cutValue
|
||||
NCoderPropID::kMatchFinder // 7 mf
|
||||
};
|
||||
PROPVARIANT pr[8];
|
||||
pr[0].vt = pr[1].vt = pr[2].vt = pr[3].vt = VT_UI4;
|
||||
pr[4].vt = pr[5].vt = pr[6].vt = VT_UI4;
|
||||
unsigned nprops = 7;
|
||||
|
||||
// setup defaults
|
||||
pr[0].uintVal = 2; // 0 .. 4
|
||||
pr[1].uintVal = 0; // 0 .. 4
|
||||
pr[2].uintVal = 3; // 0 .. 8
|
||||
pr[3].uintVal = 4 * 1024 * 1024; // 1 .. 2**30
|
||||
pr[4].uintVal = 2;
|
||||
pr[5].uintVal = 64; // 5 .. 273
|
||||
pr[6].uintVal = 0;
|
||||
#ifdef COMPRESS_MF_BT4
|
||||
static wchar_t matchfinder[] = L"BT4";
|
||||
assert(NCompress::NLZMA::FindMatchFinder(matchfinder) >= 0);
|
||||
pr[nprops].vt = VT_BSTR;
|
||||
pr[nprops].bstrVal = matchfinder;
|
||||
nprops++;
|
||||
#endif
|
||||
#if 1
|
||||
pr[0].uintVal = lzma_compress_config_t::pos_bits_t::default_value_c;
|
||||
pr[1].uintVal = lzma_compress_config_t::lit_pos_bits_t::default_value_c;
|
||||
pr[2].uintVal = lzma_compress_config_t::lit_context_bits_t::default_value_c;
|
||||
pr[3].uintVal = lzma_compress_config_t::dict_size_t::default_value_c;
|
||||
pr[5].uintVal = lzma_compress_config_t::num_fast_bytes_t::default_value_c;
|
||||
#endif
|
||||
// method overrides
|
||||
if (method >= 0x100) {
|
||||
pr[0].uintVal = (method >> 16) & 15;
|
||||
pr[1].uintVal = (method >> 12) & 15;
|
||||
pr[2].uintVal = (method >> 8) & 15;
|
||||
}
|
||||
#if 0
|
||||
// DEBUG - set sizes so that we use a maxmimum amount of stack.
|
||||
// These settings cause res->num_probs == 3147574, i.e. we will
|
||||
// need about 6 MiB of stack during runtime decompression.
|
||||
pr[1].uintVal = 4;
|
||||
pr[2].uintVal = 8;
|
||||
#endif
|
||||
|
||||
// FIXME: tune these settings according to level
|
||||
switch (level)
|
||||
{
|
||||
case 1:
|
||||
pr[3].uintVal = 256 * 1024;
|
||||
pr[4].uintVal = 0;
|
||||
pr[5].uintVal = 8;
|
||||
break;
|
||||
case 2:
|
||||
pr[3].uintVal = 256 * 1024;
|
||||
pr[4].uintVal = 0;
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
case 4:
|
||||
break;
|
||||
case 5:
|
||||
break;
|
||||
case 6:
|
||||
break;
|
||||
case 7:
|
||||
break;
|
||||
case 8:
|
||||
break;
|
||||
case 9:
|
||||
pr[3].uintVal = 8 * 1024 * 1024;
|
||||
break;
|
||||
case 10:
|
||||
pr[3].uintVal = src_len;
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
|
||||
// cconf overrides
|
||||
if (lcconf)
|
||||
{
|
||||
oassign(pr[0].uintVal, lcconf->pos_bits);
|
||||
oassign(pr[1].uintVal, lcconf->lit_pos_bits);
|
||||
oassign(pr[2].uintVal, lcconf->lit_context_bits);
|
||||
oassign(pr[3].uintVal, lcconf->dict_size);
|
||||
oassign(pr[5].uintVal, lcconf->num_fast_bytes);
|
||||
}
|
||||
|
||||
// limit dictionary size
|
||||
if (pr[3].uintVal > src_len)
|
||||
pr[3].uintVal = src_len;
|
||||
|
||||
// limit num_probs
|
||||
if (lcconf && lcconf->max_num_probs)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
unsigned n = 1846 + (768 << (pr[2].uintVal + pr[1].uintVal));
|
||||
if (n <= lcconf->max_num_probs)
|
||||
break;
|
||||
if (pr[1].uintVal > pr[2].uintVal)
|
||||
{
|
||||
if (pr[1].uintVal == 0)
|
||||
goto error;
|
||||
pr[1].uintVal -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pr[2].uintVal == 0)
|
||||
goto error;
|
||||
pr[2].uintVal -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res->pos_bits = pr[0].uintVal;
|
||||
res->lit_pos_bits = pr[1].uintVal;
|
||||
res->lit_context_bits = pr[2].uintVal;
|
||||
res->dict_size = pr[3].uintVal;
|
||||
res->fast_mode = pr[4].uintVal;
|
||||
res->num_fast_bytes = pr[5].uintVal;
|
||||
res->match_finder_cycles = pr[6].uintVal;
|
||||
//res->num_probs = LzmaGetNumProbs(&s.Properties));
|
||||
//res->num_probs = (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
|
||||
res->num_probs = 1846 + (768 << (res->lit_context_bits + res->lit_pos_bits));
|
||||
//printf("\nlzma_compress config: %u %u %u %u %u\n", res->pos_bits, res->lit_pos_bits, res->lit_context_bits, res->dict_size, res->num_probs);
|
||||
|
||||
#ifndef _NO_EXCEPTIONS
|
||||
try {
|
||||
#else
|
||||
# error
|
||||
#endif
|
||||
|
||||
if (enc.SetCoderProperties(propIDs, pr, nprops) != S_OK)
|
||||
goto error;
|
||||
if (enc.WriteCoderProperties(&os) != S_OK)
|
||||
goto error;
|
||||
if (os.overflow) {
|
||||
//r = UPX_E_OUTPUT_OVERRUN;
|
||||
r = UPX_E_NOT_COMPRESSIBLE;
|
||||
goto error;
|
||||
}
|
||||
assert(os.b_pos == 5);
|
||||
#if defined(USE_LZMA_PROPERTIES)
|
||||
os.b_pos = 1;
|
||||
#else
|
||||
os.b_pos = 0;
|
||||
// extra stuff in first byte: 5 high bits convenience for stub decompressor
|
||||
unsigned t = res->lit_context_bits + res->lit_pos_bits;
|
||||
os.WriteByte((t << 3) | res->pos_bits);
|
||||
os.WriteByte((res->lit_pos_bits << 4) | (res->lit_context_bits));
|
||||
#endif
|
||||
|
||||
rh = enc.Code(&is, &os, NULL, NULL, &progress);
|
||||
|
||||
#ifndef _NO_EXCEPTIONS
|
||||
} catch (...) { rh = E_OUTOFMEMORY; }
|
||||
#endif
|
||||
|
||||
assert(is.b_pos <= src_len);
|
||||
assert(os.b_pos <= *dst_len);
|
||||
if (rh == E_OUTOFMEMORY)
|
||||
r = UPX_E_OUT_OF_MEMORY;
|
||||
else if (os.overflow)
|
||||
{
|
||||
assert(os.b_pos == *dst_len);
|
||||
//r = UPX_E_OUTPUT_OVERRUN;
|
||||
r = UPX_E_NOT_COMPRESSIBLE;
|
||||
}
|
||||
else if (rh == S_OK)
|
||||
{
|
||||
assert(is.b_pos == src_len);
|
||||
r = UPX_E_OK;
|
||||
}
|
||||
|
||||
error:
|
||||
*dst_len = os.b_pos;
|
||||
//printf("\nlzma_compress: %d: %u %u %u %u %u, %u - > %u\n", r, res->pos_bits, res->lit_pos_bits, res->lit_context_bits, res->dict_size, res->num_probs, src_len, *dst_len);
|
||||
//printf("%u %u %u\n", is.__m_RefCount, os.__m_RefCount, progress.__m_RefCount);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// decompress
|
||||
**************************************************************************/
|
||||
|
||||
#undef _LZMA_IN_CB
|
||||
#undef _LZMA_OUT_READ
|
||||
#undef _LZMA_PROB32
|
||||
#undef _LZMA_LOC_OPT
|
||||
#if (WITH_LZMA >= 0x449)
|
||||
# include "C/Compress/Lzma/LzmaDecode.h"
|
||||
# include "C/Compress/Lzma/LzmaDecode.c"
|
||||
#else
|
||||
# include "C/7zip/Compress/LZMA_C/LzmaDecode.h"
|
||||
# include "C/7zip/Compress/LZMA_C/LzmaDecode.c"
|
||||
#endif
|
||||
|
||||
int upx_lzma_decompress ( const upx_bytep src, unsigned src_len,
|
||||
upx_bytep dst, unsigned* dst_len,
|
||||
int method,
|
||||
const upx_compress_result_t *cresult )
|
||||
{
|
||||
assert(M_IS_LZMA(method));
|
||||
// see res->num_probs above
|
||||
COMPILE_TIME_ASSERT(sizeof(CProb) == 2)
|
||||
COMPILE_TIME_ASSERT(LZMA_BASE_SIZE == 1846)
|
||||
COMPILE_TIME_ASSERT(LZMA_LIT_SIZE == 768)
|
||||
|
||||
CLzmaDecoderState s; memset(&s, 0, sizeof(s));
|
||||
SizeT src_out = 0, dst_out = 0;
|
||||
int r = UPX_E_ERROR;
|
||||
int rh;
|
||||
|
||||
#if defined(USE_LZMA_PROPERTIES)
|
||||
if (src_len < 2)
|
||||
goto error;
|
||||
rh = LzmaDecodeProperties(&s.Properties, src, src_len);
|
||||
if (rh != 0)
|
||||
goto error;
|
||||
src += 1; src_len -= 1;
|
||||
#else
|
||||
if (src_len < 3)
|
||||
goto error;
|
||||
s.Properties.pb = src[0] & 7;
|
||||
s.Properties.lp = (src[1] >> 4);
|
||||
s.Properties.lc = src[1] & 15;
|
||||
if (s.Properties.pb >= 5) goto error;
|
||||
if (s.Properties.lp >= 5) goto error;
|
||||
if (s.Properties.lc >= 9) goto error;
|
||||
// extra
|
||||
if ((src[0] >> 3) != s.Properties.lc + s.Properties.lp) goto error;
|
||||
src += 2; src_len -= 2;
|
||||
#endif
|
||||
|
||||
if (cresult)
|
||||
{
|
||||
assert(cresult->method == method);
|
||||
assert(cresult->result_lzma.pos_bits == (unsigned) s.Properties.pb);
|
||||
assert(cresult->result_lzma.lit_pos_bits == (unsigned) s.Properties.lp);
|
||||
assert(cresult->result_lzma.lit_context_bits == (unsigned) s.Properties.lc);
|
||||
assert(cresult->result_lzma.num_probs == (unsigned) LzmaGetNumProbs(&s.Properties));
|
||||
const lzma_compress_result_t *res = &cresult->result_lzma;
|
||||
UNUSED(res);
|
||||
//printf("\nlzma_decompress config: %u %u %u %u %u\n", res->pos_bits, res->lit_pos_bits, res->lit_context_bits, res->dict_size, res->num_probs);
|
||||
}
|
||||
s.Probs = (CProb *) malloc(sizeof(CProb) * LzmaGetNumProbs(&s.Properties));
|
||||
if (!s.Probs)
|
||||
{
|
||||
r = UPX_E_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
}
|
||||
rh = LzmaDecode(&s, src, src_len, &src_out, dst, *dst_len, &dst_out);
|
||||
assert(src_out <= src_len);
|
||||
assert(dst_out <= *dst_len);
|
||||
if (rh == 0)
|
||||
{
|
||||
r = UPX_E_OK;
|
||||
if (src_out != src_len)
|
||||
r = UPX_E_INPUT_NOT_CONSUMED;
|
||||
}
|
||||
|
||||
error:
|
||||
*dst_len = dst_out;
|
||||
free(s.Probs);
|
||||
|
||||
UNUSED(cresult);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// test_overlap - see <ucl/ucl.h> for semantics
|
||||
**************************************************************************/
|
||||
|
||||
int upx_lzma_test_overlap ( const upx_bytep buf,
|
||||
const upx_bytep tbuf,
|
||||
unsigned src_off, unsigned src_len,
|
||||
unsigned* dst_len,
|
||||
int method,
|
||||
const upx_compress_result_t *cresult )
|
||||
{
|
||||
assert(M_IS_LZMA(method));
|
||||
|
||||
MemBuffer b(src_off + src_len);
|
||||
memcpy(b + src_off, buf + src_off, src_len);
|
||||
unsigned saved_dst_len = *dst_len;
|
||||
int r = upx_lzma_decompress(b + src_off, src_len, b, dst_len, method, cresult);
|
||||
if (r != UPX_E_OK)
|
||||
return r;
|
||||
if (*dst_len != saved_dst_len)
|
||||
return UPX_E_ERROR;
|
||||
// NOTE: there is a very tiny possibility that decompression has
|
||||
// succeeded but the data is not restored correctly because of
|
||||
// in-place buffer overlapping.
|
||||
if (tbuf != NULL && memcmp(tbuf, b, *dst_len) != 0)
|
||||
return UPX_E_ERROR;
|
||||
return UPX_E_OK;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// misc
|
||||
**************************************************************************/
|
||||
|
||||
const char *upx_lzma_version_string(void)
|
||||
{
|
||||
#if (WITH_LZMA + 0 == 0x457)
|
||||
return "4.57";
|
||||
#elif (WITH_LZMA + 0 == 0x449)
|
||||
return "4.49";
|
||||
#elif (WITH_LZMA + 0 == 0x443)
|
||||
return "4.43";
|
||||
#else
|
||||
# error "unknown WITH_LZMA version"
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#endif /* WITH_LZMA */
|
||||
/*
|
||||
vi:ts=4:et:nowrap
|
||||
*/
|
||||
|
||||
@@ -1,294 +0,0 @@
|
||||
/* compress_ucl.cpp --
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 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@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
#include "compress.h"
|
||||
#if !defined(WITH_UCL)
|
||||
extern int compress_ucl_dummy;
|
||||
int compress_ucl_dummy = 0;
|
||||
#else
|
||||
|
||||
#if 1 && !defined(UCL_USE_ASM) && (ACC_ARCH_I386)
|
||||
# if (ACC_CC_GNUC || ACC_CC_INTELC || ACC_CC_MSC || ACC_CC_WATCOMC)
|
||||
# define UCL_USE_ASM
|
||||
# endif
|
||||
#endif
|
||||
#if defined(UCL_NO_ASM)
|
||||
# undef UCL_USE_ASM
|
||||
#endif
|
||||
#if defined(ACC_CFG_NO_UNALIGNED)
|
||||
# undef UCL_USE_ASM
|
||||
#endif
|
||||
#if 1 && defined(UCL_USE_ASM)
|
||||
# include <ucl/ucl_asm.h>
|
||||
# define ucl_nrv2b_decompress_safe_8 ucl_nrv2b_decompress_asm_safe_8
|
||||
# define ucl_nrv2b_decompress_safe_le16 ucl_nrv2b_decompress_asm_safe_le16
|
||||
# define ucl_nrv2b_decompress_safe_le32 ucl_nrv2b_decompress_asm_safe_le32
|
||||
# define ucl_nrv2d_decompress_safe_8 ucl_nrv2d_decompress_asm_safe_8
|
||||
# define ucl_nrv2d_decompress_safe_le16 ucl_nrv2d_decompress_asm_safe_le16
|
||||
# define ucl_nrv2d_decompress_safe_le32 ucl_nrv2d_decompress_asm_safe_le32
|
||||
# define ucl_nrv2e_decompress_safe_8 ucl_nrv2e_decompress_asm_safe_8
|
||||
# define ucl_nrv2e_decompress_safe_le16 ucl_nrv2e_decompress_asm_safe_le16
|
||||
# define ucl_nrv2e_decompress_safe_le32 ucl_nrv2e_decompress_asm_safe_le32
|
||||
#endif
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
static int convert_errno_from_ucl(int r)
|
||||
{
|
||||
switch (r)
|
||||
{
|
||||
case UCL_E_OK: return UPX_E_OK;
|
||||
case UCL_E_ERROR: return UPX_E_ERROR;
|
||||
case UCL_E_OUT_OF_MEMORY: return UPX_E_OUT_OF_MEMORY;
|
||||
case UCL_E_NOT_COMPRESSIBLE: return UPX_E_NOT_COMPRESSIBLE;
|
||||
case UCL_E_INPUT_OVERRUN: return UPX_E_INPUT_OVERRUN;
|
||||
case UCL_E_OUTPUT_OVERRUN: return UPX_E_OUTPUT_OVERRUN;
|
||||
case UCL_E_LOOKBEHIND_OVERRUN: return UPX_E_LOOKBEHIND_OVERRUN;
|
||||
case UCL_E_EOF_NOT_FOUND: return UPX_E_EOF_NOT_FOUND;
|
||||
case UCL_E_INPUT_NOT_CONSUMED: return UPX_E_INPUT_NOT_CONSUMED;
|
||||
// case UCL_E_NOT_YET_IMPLEMENTED: return UPX_E_NOT_YET_IMPLEMENTED;
|
||||
case UCL_E_INVALID_ARGUMENT: return UPX_E_INVALID_ARGUMENT;
|
||||
// UCL extra:
|
||||
case UCL_E_OVERLAP_OVERRUN: return UPX_E_ERROR;
|
||||
}
|
||||
return UPX_E_ERROR;
|
||||
}
|
||||
|
||||
|
||||
extern "C" {
|
||||
static void wrap_nprogress_ucl(ucl_uint a, ucl_uint b, int state, ucl_voidp user)
|
||||
{
|
||||
if (state != -1 && state != 3) return;
|
||||
upx_callback_p cb = (upx_callback_p) user;
|
||||
if (cb && cb->nprogress)
|
||||
cb->nprogress(cb, a, b);
|
||||
}}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
int upx_ucl_compress ( const upx_bytep src, unsigned src_len,
|
||||
upx_bytep dst, unsigned* dst_len,
|
||||
upx_callback_p cb_parm,
|
||||
int method, int level,
|
||||
const upx_compress_config_t *cconf_parm,
|
||||
upx_compress_result_t *cresult )
|
||||
{
|
||||
int r;
|
||||
assert(level > 0); assert(cresult != NULL);
|
||||
|
||||
COMPILE_TIME_ASSERT(sizeof(ucl_compress_config_t) == sizeof(REAL_ucl_compress_config_t))
|
||||
|
||||
ucl_progress_callback_t cb;
|
||||
cb.callback = 0;
|
||||
cb.user = NULL;
|
||||
if (cb_parm && cb_parm->nprogress) {
|
||||
cb.callback = wrap_nprogress_ucl;
|
||||
cb.user = cb_parm;
|
||||
}
|
||||
|
||||
ucl_compress_config_t cconf; cconf.reset();
|
||||
if (cconf_parm)
|
||||
cconf = cconf_parm->conf_ucl; // struct copy
|
||||
|
||||
ucl_uint *res = cresult->result_ucl.result;
|
||||
// assume no info available - fill in worst case results
|
||||
//res[0] = 1; // min_offset_found - NOT USED
|
||||
res[1] = src_len - 1; // max_offset_found
|
||||
//res[2] = 2; // min_match_found - NOT USED
|
||||
res[3] = src_len - 1; // max_match_found
|
||||
//res[4] = 1; // min_run_found - NOT USED
|
||||
res[5] = src_len; // max_run_found
|
||||
res[6] = 1; // first_offset_found
|
||||
//res[7] = 999999; // same_match_offsets_found - NOT USED
|
||||
|
||||
// prepare bit-buffer settings
|
||||
cconf.bb_endian = 0;
|
||||
cconf.bb_size = 0;
|
||||
if (method >= M_NRV2B_LE32 && method <= M_NRV2E_LE16)
|
||||
{
|
||||
static const unsigned char sizes[3] = {32, 8, 16};
|
||||
cconf.bb_size = sizes[(method - M_NRV2B_LE32) % 3];
|
||||
}
|
||||
else {
|
||||
throwInternalError("unknown compression method");
|
||||
return UPX_E_ERROR;
|
||||
}
|
||||
|
||||
// optimize compression parms
|
||||
if (level <= 3 && cconf.max_offset == UCL_UINT_MAX)
|
||||
cconf.max_offset = 8*1024-1;
|
||||
else if (level == 4 && cconf.max_offset == UCL_UINT_MAX)
|
||||
cconf.max_offset = 32*1024-1;
|
||||
|
||||
if M_IS_NRV2B(method)
|
||||
r = ucl_nrv2b_99_compress(src, src_len, dst, dst_len,
|
||||
&cb, level, &cconf, res);
|
||||
else if M_IS_NRV2D(method)
|
||||
r = ucl_nrv2d_99_compress(src, src_len, dst, dst_len,
|
||||
&cb, level, &cconf, res);
|
||||
else if M_IS_NRV2E(method)
|
||||
r = ucl_nrv2e_99_compress(src, src_len, dst, dst_len,
|
||||
&cb, level, &cconf, res);
|
||||
else {
|
||||
throwInternalError("unknown compression method");
|
||||
return UPX_E_ERROR;
|
||||
}
|
||||
|
||||
// make sure first_offset_found is set
|
||||
if (res[6] == 0)
|
||||
res[6] = 1;
|
||||
|
||||
return convert_errno_from_ucl(r);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
int upx_ucl_decompress ( const upx_bytep src, unsigned src_len,
|
||||
upx_bytep dst, unsigned* dst_len,
|
||||
int method,
|
||||
const upx_compress_result_t *cresult )
|
||||
{
|
||||
int r;
|
||||
|
||||
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;
|
||||
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;
|
||||
default:
|
||||
throwInternalError("unknown decompression method");
|
||||
return UPX_E_ERROR;
|
||||
}
|
||||
|
||||
UNUSED(cresult);
|
||||
return convert_errno_from_ucl(r);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
int upx_ucl_test_overlap ( const upx_bytep buf,
|
||||
const upx_bytep tbuf,
|
||||
unsigned src_off, unsigned src_len,
|
||||
unsigned* dst_len,
|
||||
int method,
|
||||
const upx_compress_result_t *cresult )
|
||||
{
|
||||
int r;
|
||||
UNUSED(tbuf); // not needed for UCL
|
||||
|
||||
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;
|
||||
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;
|
||||
default:
|
||||
throwInternalError("unknown decompression method");
|
||||
return UPX_E_ERROR;
|
||||
}
|
||||
|
||||
UNUSED(cresult);
|
||||
return convert_errno_from_ucl(r);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// misc
|
||||
**************************************************************************/
|
||||
|
||||
const char *upx_ucl_version_string(void)
|
||||
{
|
||||
return ucl_version_string();
|
||||
}
|
||||
|
||||
|
||||
#endif /* WITH_UCL */
|
||||
/*
|
||||
vi:ts=4:et:nowrap
|
||||
*/
|
||||
|
||||
@@ -1,235 +0,0 @@
|
||||
/* compress_zlib.cpp --
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 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@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
#include "compress.h"
|
||||
#include "mem.h"
|
||||
|
||||
|
||||
void zlib_compress_config_t::reset()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
|
||||
mem_level.reset();
|
||||
window_bits.reset();
|
||||
strategy.reset();
|
||||
}
|
||||
|
||||
|
||||
#if !defined(WITH_ZLIB)
|
||||
extern int compress_zlib_dummy;
|
||||
int compress_zlib_dummy = 0;
|
||||
#else
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
|
||||
static int convert_errno_from_zlib(int zr)
|
||||
{
|
||||
switch (zr)
|
||||
{
|
||||
case Z_OK: return UPX_E_OK;
|
||||
case Z_DATA_ERROR: return UPX_E_ERROR;
|
||||
case Z_NEED_DICT: return UPX_E_ERROR;
|
||||
}
|
||||
return UPX_E_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
int upx_zlib_compress ( const upx_bytep src, unsigned src_len,
|
||||
upx_bytep dst, unsigned* dst_len,
|
||||
upx_callback_p cb_parm,
|
||||
int method, int level,
|
||||
const upx_compress_config_t *cconf_parm,
|
||||
upx_compress_result_t *cresult )
|
||||
{
|
||||
assert(method == M_DEFLATE);
|
||||
assert(level > 0); assert(cresult != NULL);
|
||||
UNUSED(cb_parm);
|
||||
int r = UPX_E_ERROR;
|
||||
int zr;
|
||||
const zlib_compress_config_t *lcconf = cconf_parm ? &cconf_parm->conf_zlib : NULL;
|
||||
zlib_compress_result_t *res = &cresult->result_zlib;
|
||||
|
||||
if (level == 10)
|
||||
level = 9;
|
||||
|
||||
zlib_compress_config_t::mem_level_t mem_level;
|
||||
zlib_compress_config_t::window_bits_t window_bits;
|
||||
zlib_compress_config_t::strategy_t strategy;
|
||||
// cconf overrides
|
||||
if (lcconf)
|
||||
{
|
||||
oassign(mem_level, lcconf->mem_level);
|
||||
oassign(window_bits, lcconf->window_bits);
|
||||
oassign(strategy, lcconf->strategy);
|
||||
}
|
||||
|
||||
res->dummy = 0;
|
||||
|
||||
z_stream s;
|
||||
s.zalloc = (alloc_func) 0;
|
||||
s.zfree = (free_func) 0;
|
||||
s.next_in = const_cast<upx_bytep>(src); // UNCONST
|
||||
s.avail_in = src_len;
|
||||
s.next_out = dst;
|
||||
s.avail_out = *dst_len;
|
||||
s.total_in = s.total_out = 0;
|
||||
|
||||
zr = deflateInit2(&s, level, Z_DEFLATED, 0 - (int)window_bits,
|
||||
mem_level, strategy);
|
||||
if (zr != Z_OK)
|
||||
goto error;
|
||||
zr = deflate(&s, Z_FINISH);
|
||||
if (zr != Z_STREAM_END)
|
||||
goto error;
|
||||
zr = deflateEnd(&s);
|
||||
if (zr != Z_OK)
|
||||
goto error;
|
||||
r = UPX_E_OK;
|
||||
goto done;
|
||||
error:
|
||||
(void) deflateEnd(&s);
|
||||
r = convert_errno_from_zlib(zr);
|
||||
if (r == UPX_E_OK)
|
||||
r = UPX_E_ERROR;
|
||||
done:
|
||||
if (r == UPX_E_OK)
|
||||
{
|
||||
if (s.avail_in != 0 || s.total_in != src_len)
|
||||
r = UPX_E_ERROR;
|
||||
}
|
||||
assert(s.total_in <= src_len);
|
||||
assert(s.total_out <= *dst_len);
|
||||
*dst_len = s.total_out;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
int upx_zlib_decompress ( const upx_bytep src, unsigned src_len,
|
||||
upx_bytep dst, unsigned* dst_len,
|
||||
int method,
|
||||
const upx_compress_result_t *cresult )
|
||||
{
|
||||
assert(method == M_DEFLATE);
|
||||
UNUSED(method);
|
||||
UNUSED(cresult);
|
||||
int r = UPX_E_ERROR;
|
||||
int zr;
|
||||
|
||||
z_stream s;
|
||||
s.zalloc = (alloc_func) 0;
|
||||
s.zfree = (free_func) 0;
|
||||
s.next_in = const_cast<upx_bytep>(src); // UNCONST
|
||||
s.avail_in = src_len;
|
||||
s.next_out = dst;
|
||||
s.avail_out = *dst_len;
|
||||
s.total_in = s.total_out = 0;
|
||||
|
||||
zr = inflateInit2(&s, -15);
|
||||
if (zr != Z_OK)
|
||||
goto error;
|
||||
zr = inflate(&s, Z_FINISH);
|
||||
if (zr != Z_STREAM_END)
|
||||
goto error;
|
||||
zr = inflateEnd(&s);
|
||||
if (zr != Z_OK)
|
||||
goto error;
|
||||
r = UPX_E_OK;
|
||||
goto done;
|
||||
error:
|
||||
(void) inflateEnd(&s);
|
||||
r = convert_errno_from_zlib(zr);
|
||||
if (r == UPX_E_OK)
|
||||
r = UPX_E_ERROR;
|
||||
done:
|
||||
if (r == UPX_E_OK)
|
||||
{
|
||||
if (s.avail_in != 0 || s.total_in != src_len)
|
||||
r = UPX_E_INPUT_NOT_CONSUMED;
|
||||
}
|
||||
assert(s.total_in <= src_len);
|
||||
assert(s.total_out <= *dst_len);
|
||||
*dst_len = s.total_out;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// test_overlap - see <ucl/ucl.h> for semantics
|
||||
**************************************************************************/
|
||||
|
||||
int upx_zlib_test_overlap ( const upx_bytep buf,
|
||||
const upx_bytep tbuf,
|
||||
unsigned src_off, unsigned src_len,
|
||||
unsigned* dst_len,
|
||||
int method,
|
||||
const upx_compress_result_t *cresult )
|
||||
{
|
||||
assert(method == M_DEFLATE);
|
||||
|
||||
MemBuffer b(src_off + src_len);
|
||||
memcpy(b + src_off, buf + src_off, src_len);
|
||||
unsigned saved_dst_len = *dst_len;
|
||||
int r = upx_zlib_decompress(b + src_off, src_len, b, dst_len, method, cresult);
|
||||
if (r != UPX_E_OK)
|
||||
return r;
|
||||
if (*dst_len != saved_dst_len)
|
||||
return UPX_E_ERROR;
|
||||
// NOTE: there is a very tiny possibility that decompression has
|
||||
// succeeded but the data is not restored correctly because of
|
||||
// in-place buffer overlapping.
|
||||
if (tbuf != NULL && memcmp(tbuf, b, *dst_len) != 0)
|
||||
return UPX_E_ERROR;
|
||||
return UPX_E_OK;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// misc
|
||||
**************************************************************************/
|
||||
|
||||
const char *upx_zlib_version_string(void)
|
||||
{
|
||||
return zlibVersion();
|
||||
}
|
||||
|
||||
|
||||
#endif /* WITH_ZLIB */
|
||||
/*
|
||||
vi:ts=4:et:nowrap
|
||||
*/
|
||||
|
||||
+446
-357
File diff suppressed because it is too large
Load Diff
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,75 +22,53 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../conf.h"
|
||||
|
||||
#include "conf.h"
|
||||
|
||||
#if defined(USE_CONSOLE)
|
||||
#if (USE_CONSOLE)
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
static int init(FILE *f, int o, int now)
|
||||
{
|
||||
static int init(FILE *f, int o, int now) {
|
||||
UNUSED(f);
|
||||
UNUSED(o);
|
||||
UNUSED(now);
|
||||
return CON_FILE;
|
||||
}
|
||||
|
||||
|
||||
static int set_fg(FILE *f, int fg)
|
||||
{
|
||||
static int set_fg(FILE *f, int fg) {
|
||||
UNUSED(f);
|
||||
UNUSED(fg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static void print0(FILE *f, const char *s)
|
||||
{
|
||||
static void print0(FILE *f, const char *s) {
|
||||
#if 1
|
||||
fputs(s,f);
|
||||
fputs(s, f);
|
||||
#else
|
||||
/* filter out all ANSI sequences */
|
||||
int c;
|
||||
while ((c = *s++) != 0)
|
||||
{
|
||||
if (c == '\033' && *s == ']')
|
||||
{
|
||||
while ((c = *s++) != 0) {
|
||||
if (c == '\033' && *s == ']') {
|
||||
while (*s && *s != 'm')
|
||||
s++;
|
||||
}
|
||||
else
|
||||
fputc(c,f);
|
||||
} else
|
||||
fputc(c, f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static bool intro(FILE *f)
|
||||
{
|
||||
static bool intro(FILE *f) {
|
||||
UNUSED(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
console_t console_file =
|
||||
{
|
||||
init,
|
||||
set_fg,
|
||||
print0,
|
||||
intro
|
||||
};
|
||||
console_t console_file = {init, set_fg, print0, intro};
|
||||
|
||||
#endif /* USE_CONSOLE */
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,33 +22,30 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../conf.h"
|
||||
|
||||
#include "conf.h"
|
||||
FILE *con_term = nullptr;
|
||||
|
||||
FILE *con_term = NULL;
|
||||
|
||||
#if defined(USE_CONSOLE)
|
||||
#if (USE_CONSOLE)
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
static console_t * const me = &console_init;
|
||||
console_t * con = &console_init;
|
||||
static console_t *const me = &console_init;
|
||||
console_t *con = &console_init;
|
||||
|
||||
int con_mode = CON_INIT;
|
||||
|
||||
|
||||
static void try_init(console_t *c, FILE *f)
|
||||
{
|
||||
static void try_init(console_t *c, FILE *f) {
|
||||
int k;
|
||||
|
||||
assert(c);
|
||||
assert(c->init);
|
||||
k = c->init(f,opt->console,con_mode);
|
||||
k = c->init(f, opt->console, con_mode);
|
||||
if (k == CON_INIT)
|
||||
return;
|
||||
#if 0
|
||||
@@ -56,11 +53,10 @@ static void try_init(console_t *c, FILE *f)
|
||||
if (k != opt->console)
|
||||
return;
|
||||
#endif
|
||||
if (k > con_mode)
|
||||
{
|
||||
if (k > con_mode) {
|
||||
con_mode = k;
|
||||
con = c;
|
||||
con->init = 0;
|
||||
con->init = nullptr;
|
||||
if (!con->set_fg)
|
||||
con->set_fg = console_none.set_fg;
|
||||
if (!con->print0)
|
||||
@@ -70,41 +66,37 @@ static void try_init(console_t *c, FILE *f)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int do_init(FILE *f)
|
||||
{
|
||||
static int do_init(FILE *f) {
|
||||
assert(con_mode == CON_INIT);
|
||||
|
||||
try_init(&console_none,f);
|
||||
try_init(&console_none, f);
|
||||
assert(con != me);
|
||||
assert(con == &console_none);
|
||||
if (opt->console == CON_NONE || opt->to_stdout)
|
||||
return con_mode;
|
||||
try_init(&console_file,f);
|
||||
try_init(&console_file, f);
|
||||
if (!acc_isatty(STDIN_FILENO) || !acc_isatty(STDOUT_FILENO) || !acc_isatty(STDERR_FILENO))
|
||||
return con_mode;
|
||||
|
||||
#if defined(USE_ANSI)
|
||||
try_init(&console_ansi_mono,f);
|
||||
try_init(&console_ansi_color,f);
|
||||
#if (USE_ANSI)
|
||||
try_init(&console_ansi_mono, f);
|
||||
try_init(&console_ansi_color, f);
|
||||
#endif
|
||||
#if defined(USE_SCREEN)
|
||||
try_init(&console_screen,f);
|
||||
#if (USE_SCREEN)
|
||||
try_init(&console_screen, f);
|
||||
#endif
|
||||
#if defined(USE_AALIB)
|
||||
try_init(&console_aalib,f);
|
||||
#if (USE_AALIB)
|
||||
try_init(&console_aalib, f);
|
||||
#endif
|
||||
|
||||
return con_mode;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
static int init(FILE *f, int o, int now)
|
||||
{
|
||||
static int init(FILE *f, int o, int now) {
|
||||
if (con != me)
|
||||
return con_mode;
|
||||
assert(o == -1);
|
||||
@@ -114,53 +106,36 @@ static int init(FILE *f, int o, int now)
|
||||
return do_init(f);
|
||||
}
|
||||
|
||||
|
||||
static int set_fg(FILE *f, int fg)
|
||||
{
|
||||
static int set_fg(FILE *f, int fg) {
|
||||
if (con == me)
|
||||
init(f,-1,-1);
|
||||
init(f, -1, -1);
|
||||
assert(con != me);
|
||||
return con->set_fg(f,fg);
|
||||
return con->set_fg(f, fg);
|
||||
}
|
||||
|
||||
|
||||
static bool intro(FILE *f)
|
||||
{
|
||||
static bool intro(FILE *f) {
|
||||
if (con == me)
|
||||
init(f,-1,-1);
|
||||
init(f, -1, -1);
|
||||
assert(con != me);
|
||||
return con->intro(f);
|
||||
}
|
||||
|
||||
console_t console_init = {init, set_fg, nullptr, intro};
|
||||
|
||||
console_t console_init =
|
||||
{
|
||||
init,
|
||||
set_fg,
|
||||
0,
|
||||
intro
|
||||
};
|
||||
|
||||
|
||||
void __acc_cdecl_va con_fprintf(FILE *f, const char *format, ...)
|
||||
{
|
||||
void con_fprintf(FILE *f, const char *format, ...) {
|
||||
va_list args;
|
||||
char buf[80*25];
|
||||
char buf[80 * 25];
|
||||
|
||||
va_start(args, format);
|
||||
upx_vsnprintf(buf, sizeof(buf), format,args);
|
||||
upx_safe_vsnprintf(buf, sizeof(buf), format, args);
|
||||
va_end(args);
|
||||
|
||||
if (con == me)
|
||||
init(f,-1,-1);
|
||||
init(f, -1, -1);
|
||||
assert(con != me);
|
||||
con->print0(f,buf);
|
||||
con->print0(f, buf);
|
||||
}
|
||||
|
||||
#endif /* USE_CONSOLE */
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,61 +22,42 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../conf.h"
|
||||
|
||||
#include "conf.h"
|
||||
|
||||
#if defined(USE_CONSOLE)
|
||||
#if (USE_CONSOLE)
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
static int init(FILE *f, int o, int now)
|
||||
{
|
||||
static int init(FILE *f, int o, int now) {
|
||||
UNUSED(f);
|
||||
UNUSED(o);
|
||||
UNUSED(now);
|
||||
return CON_NONE;
|
||||
}
|
||||
|
||||
|
||||
static int set_fg(FILE *f, int fg)
|
||||
{
|
||||
static int set_fg(FILE *f, int fg) {
|
||||
UNUSED(f);
|
||||
UNUSED(fg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static void print0(FILE *f, const char *s)
|
||||
{
|
||||
static void print0(FILE *f, const char *s) {
|
||||
UNUSED(f);
|
||||
UNUSED(s);
|
||||
}
|
||||
|
||||
|
||||
static bool intro(FILE *f)
|
||||
{
|
||||
static bool intro(FILE *f) {
|
||||
UNUSED(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
console_t console_none =
|
||||
{
|
||||
init,
|
||||
set_fg,
|
||||
print0,
|
||||
intro
|
||||
};
|
||||
console_t console_none = {init, set_fg, print0, intro};
|
||||
|
||||
#endif /* USE_CONSOLE */
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,29 +22,26 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../conf.h"
|
||||
|
||||
#include "conf.h"
|
||||
|
||||
#if defined(USE_SCREEN)
|
||||
#if (USE_SCREEN)
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
#define mask_fg 0x0f
|
||||
#define mask_bg 0xf0
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
static int do_init(screen_t *s, int fd)
|
||||
{
|
||||
static int do_init(screen_t *s, int fd) {
|
||||
int fg, bg;
|
||||
|
||||
if (s->init(s,fd) != 0)
|
||||
if (s->init(s, fd) != 0)
|
||||
return -1;
|
||||
|
||||
if (s->getCols(s) < 80 || s->getCols(s) > 256)
|
||||
@@ -59,88 +56,78 @@ static int do_init(screen_t *s, int fd)
|
||||
if (fg == (bg >> 4))
|
||||
return -1;
|
||||
if (bg != BG_BLACK)
|
||||
if (!s->isMono(s))
|
||||
{
|
||||
/* return 0; */ /* we could emulate ANSI mono */
|
||||
if (!s->isMono(s)) {
|
||||
/* return 0; */ /* we could emulate ANSI mono */
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static screen_t *do_construct(screen_t *s, int fd)
|
||||
{
|
||||
static screen_t *do_construct(screen_t *s, int fd) {
|
||||
if (!s)
|
||||
return NULL;
|
||||
if (do_init(s,fd) != 0)
|
||||
{
|
||||
return nullptr;
|
||||
if (do_init(s, fd) != 0) {
|
||||
s->destroy(s);
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
static screen_t *screen = NULL;
|
||||
static screen_t *screen = nullptr;
|
||||
|
||||
static void __acc_cdecl_atexit do_destroy(void)
|
||||
{
|
||||
if (screen)
|
||||
{
|
||||
static void __acc_cdecl_atexit do_destroy(void) {
|
||||
if (screen) {
|
||||
if (screen->atExit)
|
||||
screen->atExit();
|
||||
screen->destroy(screen);
|
||||
screen = NULL;
|
||||
screen = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int mode = -1;
|
||||
static int init_fg = -1;
|
||||
static int init_bg = -1;
|
||||
static int cur_fg = -1;
|
||||
static int cur_bg = -1;
|
||||
|
||||
|
||||
static int init(FILE *f, int o, int now)
|
||||
{
|
||||
static int init(FILE *f, int o, int now) {
|
||||
int fd = fileno(f);
|
||||
int n;
|
||||
|
||||
UNUSED(now);
|
||||
assert(screen == NULL);
|
||||
assert(screen == nullptr);
|
||||
|
||||
if (o == CON_SCREEN)
|
||||
n = CON_SCREEN;
|
||||
else if (o == CON_INIT) /* use by default */
|
||||
else if (o == CON_INIT) /* use by default */
|
||||
n = CON_SCREEN;
|
||||
else if (o == CON_ANSI_COLOR) /* can emulate ANSI color */
|
||||
else if (o == CON_ANSI_COLOR) /* can emulate ANSI color */
|
||||
n = CON_ANSI_COLOR;
|
||||
else if (o == CON_ANSI_MONO) /* can emulate ANSI mono */
|
||||
else if (o == CON_ANSI_MONO) /* can emulate ANSI mono */
|
||||
n = CON_ANSI_MONO;
|
||||
else
|
||||
return CON_INIT;
|
||||
|
||||
#if defined(__DJGPP__)
|
||||
#if (ACC_OS_DOS32) && defined(__DJGPP__)
|
||||
if (!screen)
|
||||
screen = do_construct(screen_djgpp2_construct(),fd);
|
||||
screen = do_construct(screen_djgpp2_construct(), fd);
|
||||
#endif
|
||||
#if defined(USE_SCREEN_WIN32)
|
||||
#if (USE_SCREEN_WIN32)
|
||||
if (!screen)
|
||||
screen = do_construct(screen_win32_construct(),fd);
|
||||
screen = do_construct(screen_win32_construct(), fd);
|
||||
#endif
|
||||
#if defined(USE_SCREEN_VCSA)
|
||||
#if (USE_SCREEN_VCSA)
|
||||
if (!screen)
|
||||
screen = do_construct(screen_vcsa_construct(),fd);
|
||||
screen = do_construct(screen_vcsa_construct(), fd);
|
||||
#endif
|
||||
#if defined(USE_SCREEN_CURSES)
|
||||
#if (USE_SCREEN_CURSES)
|
||||
if (!screen && o == CON_SCREEN)
|
||||
screen = do_construct(screen_curses_construct(),fd);
|
||||
screen = do_construct(screen_curses_construct(), fd);
|
||||
#endif
|
||||
if (!screen)
|
||||
return CON_INIT;
|
||||
@@ -155,19 +142,16 @@ static int init(FILE *f, int o, int now)
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
static int set_fg(FILE *f, int fg)
|
||||
{
|
||||
static int set_fg(FILE *f, int fg) {
|
||||
const int last_fg = cur_fg;
|
||||
int f1 = fg & mask_fg;
|
||||
int f2 = init_fg & mask_fg;
|
||||
|
||||
UNUSED(f);
|
||||
cur_fg = fg;
|
||||
if (screen->isMono(screen))
|
||||
{
|
||||
if (screen->isMono(screen)) {
|
||||
const int b = (init_bg & mask_bg) >> 4;
|
||||
if (fg == -1) /* restore startup fg */
|
||||
if (fg == -1) /* restore startup fg */
|
||||
f1 = f2;
|
||||
else if (b == 0)
|
||||
f1 = (f2 <= 8) ? 15 : 8;
|
||||
@@ -175,19 +159,15 @@ static int set_fg(FILE *f, int fg)
|
||||
f1 = (f2 == 0) ? 15 : 0;
|
||||
else
|
||||
f1 = (f2 == 0) ? 8 : 0;
|
||||
}
|
||||
else if (con_mode == CON_ANSI_MONO && f1 != f2)
|
||||
{
|
||||
} else if (con_mode == CON_ANSI_MONO && f1 != f2) {
|
||||
f1 = f2 ^ 0x08;
|
||||
}
|
||||
|
||||
screen->setFg(screen,f1 & mask_fg);
|
||||
screen->setFg(screen, f1 & mask_fg);
|
||||
return last_fg;
|
||||
}
|
||||
|
||||
|
||||
static void print0(FILE *f, const char *ss)
|
||||
{
|
||||
static void print0(FILE *f, const char *ss) {
|
||||
int cx, cy;
|
||||
int old_cx = 0, old_cy = 0;
|
||||
const int sx = screen->getCols(screen);
|
||||
@@ -199,57 +179,47 @@ static void print0(FILE *f, const char *ss)
|
||||
// scrollUp() under Win32 is *extremely* slow.
|
||||
UNUSED(f);
|
||||
|
||||
screen->getCursor(screen,&old_cx,&old_cy);
|
||||
cx = old_cx; cy = old_cy;
|
||||
screen->getCursor(screen, &old_cx, &old_cy);
|
||||
cx = old_cx;
|
||||
cy = old_cy;
|
||||
|
||||
for (pass = 0; pass < 2; pass++)
|
||||
{
|
||||
for (pass = 0; pass < 2; pass++) {
|
||||
const char *s = ss;
|
||||
// char buffer for pass 2
|
||||
char p[256+1];
|
||||
char p[256 + 1];
|
||||
int pi = 0, px = 0, py = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;) {
|
||||
// walk over whitespace
|
||||
for (;;)
|
||||
{
|
||||
if (*s == '\n')
|
||||
{
|
||||
for (;;) {
|
||||
if (*s == '\n') {
|
||||
cx = 0;
|
||||
cy++;
|
||||
}
|
||||
else if (*s == '\r')
|
||||
{
|
||||
} else if (*s == '\r') {
|
||||
cx = 0;
|
||||
if (pass > 0 && cy < sy)
|
||||
screen->clearLine(screen,cy);
|
||||
}
|
||||
else
|
||||
screen->clearLine(screen, cy);
|
||||
} else
|
||||
break;
|
||||
s++;
|
||||
}
|
||||
// adjust cursor
|
||||
if (cx >= sx)
|
||||
{
|
||||
if (cx >= sx) {
|
||||
cx = 0;
|
||||
cy++;
|
||||
}
|
||||
if (pass > 0)
|
||||
{
|
||||
if (pass > 0) {
|
||||
// check if we should print something
|
||||
if (pi > 0 && (*s == 0 || py != cy))
|
||||
{
|
||||
if (pi > 0 && (*s == 0 || py != cy)) {
|
||||
p[pi] = 0;
|
||||
screen->putString(screen,p,px,py);
|
||||
screen->putString(screen, p, px, py);
|
||||
pi = 0;
|
||||
}
|
||||
// check if we should scroll even more (this can happen
|
||||
// if the string is longer than sy lines)
|
||||
if (cy >= sy)
|
||||
{
|
||||
if (cy >= sy) {
|
||||
int scroll_y = cy - sy + 1;
|
||||
screen->scrollUp(screen,scroll_y);
|
||||
screen->scrollUp(screen, scroll_y);
|
||||
cy -= scroll_y;
|
||||
if (cy < 0)
|
||||
cy = 0;
|
||||
@@ -258,11 +228,9 @@ static void print0(FILE *f, const char *ss)
|
||||
// done ?
|
||||
if (*s == 0)
|
||||
break;
|
||||
if (pass > 0)
|
||||
{
|
||||
if (pass > 0) {
|
||||
// store current char
|
||||
if (pi == 0)
|
||||
{
|
||||
if (pi == 0) {
|
||||
px = cx;
|
||||
py = cy;
|
||||
}
|
||||
@@ -273,52 +241,35 @@ static void print0(FILE *f, const char *ss)
|
||||
s++;
|
||||
}
|
||||
|
||||
if (pass == 0)
|
||||
{
|
||||
if (pass == 0) {
|
||||
// end of pass 1 - scroll up, restore cursor
|
||||
if (cy >= sy)
|
||||
{
|
||||
if (cy >= sy) {
|
||||
int scroll_y = cy - sy + 1;
|
||||
screen->scrollUp(screen,scroll_y);
|
||||
screen->scrollUp(screen, scroll_y);
|
||||
cy = old_cy - scroll_y;
|
||||
if (cy < 0)
|
||||
cy = 0;
|
||||
}
|
||||
else
|
||||
} else
|
||||
cy = old_cy;
|
||||
cx = old_cx;
|
||||
}
|
||||
}
|
||||
|
||||
screen->setCursor(screen,cx,cy);
|
||||
screen->setCursor(screen, cx, cy);
|
||||
screen->refresh(screen);
|
||||
}
|
||||
|
||||
|
||||
static bool intro(FILE *f)
|
||||
{
|
||||
static bool intro(FILE *f) {
|
||||
UNUSED(f);
|
||||
#if defined(USE_FRAMES)
|
||||
#if (USE_FRAMES)
|
||||
if (screen->intro)
|
||||
return screen->intro(screen,screen_show_frames);
|
||||
return screen->intro(screen, screen_show_frames);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
console_t console_screen =
|
||||
{
|
||||
init,
|
||||
set_fg,
|
||||
print0,
|
||||
intro
|
||||
};
|
||||
|
||||
console_t console_screen = {init, set_fg, print0, intro};
|
||||
|
||||
#endif /* USE_SCREEN */
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,10 +22,10 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
@@ -39,133 +39,113 @@
|
||||
#undef USE_SCREEN_WIN32
|
||||
#undef USE_FRAMES
|
||||
|
||||
#if defined(WITH_GUI) && !defined(NO_CONSOLE)
|
||||
# define NO_CONSOLE
|
||||
#if 1 && (WITH_GUI) && !defined(NO_CONSOLE)
|
||||
#define NO_CONSOLE 1
|
||||
#endif
|
||||
|
||||
#if 1 && defined(__linux__)
|
||||
# define USE_SCREEN
|
||||
# define USE_SCREEN_VCSA
|
||||
# if !defined(HAVE_LINUX_KD_H)
|
||||
# undef USE_SCREEN
|
||||
# undef USE_SCREEN_VCSA
|
||||
# endif
|
||||
# if !defined(HAVE_LINUX_KDEV_T_H) || !defined(HAVE_LINUX_MAJOR_H)
|
||||
# undef USE_SCREEN
|
||||
# undef USE_SCREEN_VCSA
|
||||
# endif
|
||||
#define USE_SCREEN 1
|
||||
#define USE_SCREEN_VCSA 1
|
||||
#if !(HAVE_LINUX_KD_H)
|
||||
#undef USE_SCREEN
|
||||
#undef USE_SCREEN_VCSA
|
||||
#endif
|
||||
#if !(HAVE_LINUX_KDEV_T_H) || !(HAVE_LINUX_MAJOR_H)
|
||||
#undef USE_SCREEN
|
||||
#undef USE_SCREEN_VCSA
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if 1 && defined(__DJGPP__)
|
||||
# define USE_SCREEN
|
||||
#if 1 && (ACC_OS_DOS32) && defined(__DJGPP__)
|
||||
#define USE_SCREEN 1
|
||||
#elif 1 && (ACC_OS_CYGWIN || ACC_OS_WIN32 || ACC_OS_WIN64)
|
||||
# define USE_SCREEN
|
||||
# define USE_SCREEN_WIN32
|
||||
#define USE_SCREEN 1
|
||||
#define USE_SCREEN_WIN32 1
|
||||
#elif 1 && (ACC_OS_EMX && defined(__RSXNT__))
|
||||
# define USE_SCREEN
|
||||
# define USE_SCREEN_WIN32
|
||||
#define USE_SCREEN 1
|
||||
#define USE_SCREEN_WIN32 1
|
||||
#elif 1 && (ACC_ARCH_M68K && ACC_OS_TOS)
|
||||
#define NO_CONSOLE 1
|
||||
#endif
|
||||
|
||||
|
||||
#if 0 || defined(NO_ANSI)
|
||||
# undef USE_ANSI
|
||||
#if 0 || (NO_ANSI)
|
||||
#undef USE_ANSI
|
||||
#endif
|
||||
#if 0 || defined(NO_SCREEN)
|
||||
# undef USE_SCREEN
|
||||
#if 0 || (NO_SCREEN)
|
||||
#undef USE_SCREEN
|
||||
#endif
|
||||
#if 0 || defined(NO_FRAMES) || !defined(USE_SCREEN)
|
||||
# undef USE_FRAMES
|
||||
#if 0 || (NO_FRAMES) || !(USE_SCREEN)
|
||||
#undef USE_FRAMES
|
||||
#endif
|
||||
#if 1
|
||||
# undef USE_FRAMES
|
||||
#undef USE_FRAMES
|
||||
#endif
|
||||
|
||||
|
||||
#if 0 || defined(USE_ANSI) || defined(USE_SCREEN)
|
||||
# define USE_CONSOLE
|
||||
#if 0 || (USE_ANSI) || (USE_SCREEN)
|
||||
#define USE_CONSOLE 1
|
||||
#endif
|
||||
|
||||
#if 0 || defined(NO_CONSOLE) || !defined(USE_CONSOLE)
|
||||
# undef USE_CONSOLE
|
||||
# undef USE_ANSI
|
||||
# undef USE_SCREEN
|
||||
# undef USE_SCREEN_VCSA
|
||||
# undef USE_SCREEN_CURSES
|
||||
# undef USE_FRAMES
|
||||
#if 0 || (NO_CONSOLE) || !(USE_CONSOLE)
|
||||
#undef USE_CONSOLE
|
||||
#undef USE_ANSI
|
||||
#undef USE_SCREEN
|
||||
#undef USE_SCREEN_VCSA
|
||||
#undef USE_SCREEN_CURSES
|
||||
#undef USE_FRAMES
|
||||
#endif
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
enum {
|
||||
CON_INIT,
|
||||
CON_NONE,
|
||||
CON_FILE,
|
||||
CON_ANSI_MONO,
|
||||
CON_ANSI_COLOR,
|
||||
CON_SCREEN,
|
||||
CON_UNUSED
|
||||
};
|
||||
enum { CON_INIT, CON_NONE, CON_FILE, CON_ANSI_MONO, CON_ANSI_COLOR, CON_SCREEN, CON_UNUSED };
|
||||
|
||||
#if (USE_CONSOLE)
|
||||
|
||||
#if defined(USE_CONSOLE)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
int (*init)(FILE *f, int, int);
|
||||
int (*set_fg)(FILE *f, int fg);
|
||||
void (*print0)(FILE *f, const char *s);
|
||||
bool (*intro)(FILE *f);
|
||||
}
|
||||
console_t;
|
||||
} console_t;
|
||||
|
||||
void con_fprintf(FILE *f, const char *format, ...) attribute_format(2, 3);
|
||||
|
||||
#if defined(__GNUC__)
|
||||
void __acc_cdecl_va con_fprintf(FILE *f, const char *format, ...)
|
||||
__attribute__((__format__(printf,2,3)));
|
||||
#else
|
||||
void __acc_cdecl_va con_fprintf(FILE *f, const char *format, ...);
|
||||
#endif
|
||||
|
||||
|
||||
#define FG_BLACK 0x00
|
||||
#define FG_BLUE 0x01
|
||||
#define FG_GREEN 0x02
|
||||
#define FG_CYAN 0x03
|
||||
#define FG_RED 0x04
|
||||
#define FG_VIOLET 0x05
|
||||
#define FG_ORANGE 0x06
|
||||
#define FG_LTGRAY 0x07
|
||||
#define FG_DKGRAY 0x08
|
||||
#define FG_BRTBLUE 0x09
|
||||
#define FG_BRTGREEN 0x0a
|
||||
#define FG_BRTCYAN 0x0b
|
||||
#define FG_BRTRED 0x0c
|
||||
#define FG_BLACK 0x00
|
||||
#define FG_BLUE 0x01
|
||||
#define FG_GREEN 0x02
|
||||
#define FG_CYAN 0x03
|
||||
#define FG_RED 0x04
|
||||
#define FG_VIOLET 0x05
|
||||
#define FG_ORANGE 0x06
|
||||
#define FG_LTGRAY 0x07
|
||||
#define FG_DKGRAY 0x08
|
||||
#define FG_BRTBLUE 0x09
|
||||
#define FG_BRTGREEN 0x0a
|
||||
#define FG_BRTCYAN 0x0b
|
||||
#define FG_BRTRED 0x0c
|
||||
#define FG_BRTVIOLET 0x0d
|
||||
#define FG_YELLOW 0x0e
|
||||
#define FG_WHITE 0x0f
|
||||
#define FG_YELLOW 0x0e
|
||||
#define FG_WHITE 0x0f
|
||||
|
||||
#define BG_BLACK 0x00
|
||||
#define BG_BLUE 0x10
|
||||
#define BG_GREEN 0x20
|
||||
#define BG_CYAN 0x30
|
||||
#define BG_RED 0x40
|
||||
#define BG_VIOLET 0x50
|
||||
#define BG_ORANGE 0x60
|
||||
#define BG_WHITE 0x70
|
||||
#define BG_BLACK 0x00
|
||||
#define BG_BLUE 0x10
|
||||
#define BG_GREEN 0x20
|
||||
#define BG_CYAN 0x30
|
||||
#define BG_RED 0x40
|
||||
#define BG_VIOLET 0x50
|
||||
#define BG_ORANGE 0x60
|
||||
#define BG_WHITE 0x70
|
||||
|
||||
#endif /* USE_CONSOLE */
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
extern FILE *con_term;
|
||||
|
||||
#if defined(USE_CONSOLE)
|
||||
#if (USE_CONSOLE)
|
||||
|
||||
extern int con_mode;
|
||||
extern console_t *con;
|
||||
@@ -177,18 +157,13 @@ extern console_t console_ansi_mono;
|
||||
extern console_t console_ansi_color;
|
||||
extern console_t console_screen;
|
||||
|
||||
|
||||
#define con_fg(f,x) con->set_fg(f,x)
|
||||
#define con_fg(f, x) con->set_fg(f, x)
|
||||
|
||||
#else
|
||||
|
||||
#define con_fg(f,x) 0
|
||||
#define con_fprintf fprintf
|
||||
#define con_fg(f, x) 0
|
||||
#define con_fprintf fprintf
|
||||
|
||||
#endif /* USE_CONSOLE */
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,23 +22,24 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../conf.h"
|
||||
|
||||
#include "conf.h"
|
||||
|
||||
#if defined(USE_SCREEN) && defined(__DJGPP__)
|
||||
#if (USE_SCREEN) && (ACC_OS_DOS32) && defined(__DJGPP__)
|
||||
#if (ACC_CC_GNUC >= 0x040300ul)
|
||||
#pragma GCC diagnostic ignored "-Wvla"
|
||||
#endif
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
#define this local_this
|
||||
#define this self
|
||||
|
||||
#define mask_fg 0x0f
|
||||
#define mask_bg 0xf0
|
||||
|
||||
/* #define USE_SCROLLBACK */
|
||||
|
||||
/* #define USE_SCROLLBACK 1 */
|
||||
|
||||
/*************************************************************************
|
||||
// direct screen access
|
||||
@@ -53,13 +54,13 @@
|
||||
#include <sys/exceptn.h>
|
||||
#include <sys/farptr.h>
|
||||
#include <sys/movedata.h>
|
||||
#define dossel _go32_info_block.selector_for_linear_memory
|
||||
#define co80 _go32_info_block.linear_address_of_primary_screen
|
||||
#define dossel _go32_info_block.selector_for_linear_memory
|
||||
#define co80 _go32_info_block.linear_address_of_primary_screen
|
||||
#undef kbhit
|
||||
|
||||
#define Cell upx_uint16_t
|
||||
|
||||
struct screen_data_t
|
||||
{
|
||||
struct screen_data_t {
|
||||
int mode;
|
||||
int cols;
|
||||
int rows;
|
||||
@@ -69,92 +70,63 @@ struct screen_data_t
|
||||
unsigned char attr;
|
||||
unsigned char init_attr;
|
||||
unsigned char empty_attr;
|
||||
unsigned short empty_cell;
|
||||
#ifdef USE_SCROLLBACK
|
||||
Cell empty_cell;
|
||||
#if USE_SCROLLBACK
|
||||
/* scrollback buffer */
|
||||
unsigned short sb_buf[32][256];
|
||||
Cell sb_buf[32][256];
|
||||
int sb_size;
|
||||
int sb_base;
|
||||
int sb_sp;
|
||||
#endif /* USE_SCROLLBACK */
|
||||
};
|
||||
|
||||
|
||||
/* atExit information */
|
||||
static struct
|
||||
{
|
||||
static struct {
|
||||
int cursor_shape;
|
||||
} ae = {
|
||||
-1
|
||||
};
|
||||
} ae = {-1};
|
||||
|
||||
|
||||
#ifdef USE_SCROLLBACK
|
||||
static __inline__ void sb_add(screen_t *this, int *val, int inc)
|
||||
{
|
||||
#if USE_SCROLLBACK
|
||||
static __inline__ void sb_add(screen_t *this, int *val, int inc) {
|
||||
*val = (*val + inc) & (this->data->sb_size - 1);
|
||||
}
|
||||
|
||||
static void sb_push(screen_t *this, const unsigned short *line, int len)
|
||||
{
|
||||
memcpy(this->data->sb_buf[this->data->sb_sp],line,len);
|
||||
sb_add(this,&this->data->sb_sp,1);
|
||||
static void sb_push(screen_t *this, const Cell *line, int len) {
|
||||
memcpy(this->data->sb_buf[this->data->sb_sp], line, len);
|
||||
sb_add(this, &this->data->sb_sp, 1);
|
||||
if (this->data->sb_sp == this->data->sb_base)
|
||||
sb_add(this,&this->data->sb_base,1);
|
||||
sb_add(this, &this->data->sb_base, 1);
|
||||
}
|
||||
|
||||
static const unsigned short *sb_pop(screen_t *this)
|
||||
{
|
||||
static const Cell *sb_pop(screen_t *this) {
|
||||
if (this->data->sb_sp == this->data->sb_base)
|
||||
return NULL;
|
||||
sb_add(this,&this->data->sb_sp,-1);
|
||||
return nullptr;
|
||||
sb_add(this, &this->data->sb_sp, -1);
|
||||
return this->data->sb_buf[this->data->sb_sp];
|
||||
}
|
||||
#endif /* USE_SCROLLBACK */
|
||||
|
||||
static void refresh(screen_t *this) { UNUSED(this); }
|
||||
|
||||
static void refresh(screen_t *this)
|
||||
{
|
||||
static __inline__ Cell make_cell(screen_t *this, int ch, int attr) {
|
||||
UNUSED(this);
|
||||
return (Cell) (((attr & 0xff) << 8) | (ch & 0xff));
|
||||
}
|
||||
|
||||
|
||||
static __inline__
|
||||
unsigned short make_cell(screen_t *this, int ch, int attr)
|
||||
{
|
||||
UNUSED(this);
|
||||
return (unsigned short) (((attr & 0xff) << 8) | (ch & 0xff));
|
||||
}
|
||||
|
||||
|
||||
static int getMode(const screen_t *this)
|
||||
{
|
||||
static int getMode(const screen_t *this) {
|
||||
UNUSED(this);
|
||||
return ScreenMode();
|
||||
}
|
||||
|
||||
|
||||
static int getPage(const screen_t *this)
|
||||
{
|
||||
static int getPage(const screen_t *this) {
|
||||
UNUSED(this);
|
||||
return _farpeekb(dossel, 0x462);
|
||||
}
|
||||
|
||||
static int getRows(const screen_t *this) { return this->data->rows; }
|
||||
|
||||
static int getRows(const screen_t *this)
|
||||
{
|
||||
return this->data->rows;
|
||||
}
|
||||
static int getCols(const screen_t *this) { return this->data->cols; }
|
||||
|
||||
|
||||
static int getCols(const screen_t *this)
|
||||
{
|
||||
return this->data->cols;
|
||||
}
|
||||
|
||||
|
||||
static int isMono(const screen_t *this)
|
||||
{
|
||||
static int isMono(const screen_t *this) {
|
||||
if (this->data->mode == 7)
|
||||
return 1;
|
||||
if ((_farpeekb(dossel, 0x465) & (4 | 16)) != 0)
|
||||
@@ -162,42 +134,26 @@ static int isMono(const screen_t *this)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getFg(const screen_t *this) { return this->data->attr & mask_fg; }
|
||||
|
||||
static int getFg(const screen_t *this)
|
||||
{
|
||||
return this->data->attr & mask_fg;
|
||||
}
|
||||
static int getBg(const screen_t *this) { return this->data->attr & mask_bg; }
|
||||
|
||||
|
||||
static int getBg(const screen_t *this)
|
||||
{
|
||||
return this->data->attr & mask_bg;
|
||||
}
|
||||
|
||||
|
||||
static void setFg(screen_t *this, int fg)
|
||||
{
|
||||
static void setFg(screen_t *this, int fg) {
|
||||
this->data->attr = (this->data->attr & mask_bg) | (fg & mask_fg);
|
||||
}
|
||||
|
||||
|
||||
static void setBg(screen_t *this, int bg)
|
||||
{
|
||||
static void setBg(screen_t *this, int bg) {
|
||||
this->data->attr = (this->data->attr & mask_fg) | (bg & mask_bg);
|
||||
}
|
||||
|
||||
|
||||
static void setCursor(screen_t *this, int x, int y)
|
||||
{
|
||||
if (x >= 0 && y >= 0 && x < this->data->cols && y < this->data->rows)
|
||||
{
|
||||
ScreenSetCursor(y,x);
|
||||
static void setCursor(screen_t *this, int x, int y) {
|
||||
if (x >= 0 && y >= 0 && x < this->data->cols && y < this->data->rows) {
|
||||
ScreenSetCursor(y, x);
|
||||
this->data->cursor_x = x;
|
||||
this->data->cursor_y = y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// I added ScreenGetCursor, because when upx prints something longer than
|
||||
// 1 line (an error message for example), the this->data->cursor_y can
|
||||
@@ -209,88 +165,71 @@ static void setCursor(screen_t *this, int x, int y)
|
||||
// the 2 passes implementation.
|
||||
*/
|
||||
|
||||
static void getCursor(const screen_t *this, int *x, int *y)
|
||||
{
|
||||
static void getCursor(const screen_t *this, int *x, int *y) {
|
||||
int cx = this->data->cursor_x;
|
||||
int cy = this->data->cursor_y;
|
||||
#if 1
|
||||
ScreenGetCursor(&cy,&cx);
|
||||
ScreenGetCursor(&cy, &cx);
|
||||
#endif
|
||||
if (x) *x = cx;
|
||||
if (y) *y = cy;
|
||||
if (x)
|
||||
*x = cx;
|
||||
if (y)
|
||||
*y = cy;
|
||||
}
|
||||
|
||||
|
||||
static void putCharAttr(screen_t *this, int ch, int attr, int x, int y)
|
||||
{
|
||||
static void putCharAttr(screen_t *this, int ch, int attr, int x, int y) {
|
||||
UNUSED(this);
|
||||
ScreenPutChar(ch,attr,x,y);
|
||||
ScreenPutChar(ch, attr, x, y);
|
||||
}
|
||||
|
||||
|
||||
static void putChar(screen_t *this, int ch, int x, int y)
|
||||
{
|
||||
ScreenPutChar(ch,this->data->attr,x,y);
|
||||
static void putChar(screen_t *this, int ch, int x, int y) {
|
||||
ScreenPutChar(ch, this->data->attr, x, y);
|
||||
}
|
||||
|
||||
|
||||
static void putStringAttr(screen_t *this, const char *s, int attr, int x, int y)
|
||||
{
|
||||
static void putStringAttr(screen_t *this, const char *s, int attr, int x, int y) {
|
||||
UNUSED(this);
|
||||
assert((int)strlen(s) <= 256);
|
||||
assert(x + (int)strlen(s) <= this->data->cols);
|
||||
ScreenPutString(s,attr,x,y);
|
||||
assert((int) strlen(s) <= 256);
|
||||
assert(x + (int) strlen(s) <= this->data->cols);
|
||||
ScreenPutString(s, attr, x, y);
|
||||
}
|
||||
|
||||
|
||||
static void putString(screen_t *this, const char *s, int x, int y)
|
||||
{
|
||||
assert((int)strlen(s) <= 256);
|
||||
assert(x + (int)strlen(s) <= this->data->cols);
|
||||
ScreenPutString(s,this->data->attr,x,y);
|
||||
static void putString(screen_t *this, const char *s, int x, int y) {
|
||||
assert((int) strlen(s) <= 256);
|
||||
assert(x + (int) strlen(s) <= this->data->cols);
|
||||
ScreenPutString(s, this->data->attr, x, y);
|
||||
}
|
||||
|
||||
|
||||
/* private */
|
||||
static void getChar(screen_t *this, int *ch, int *attr, int x, int y)
|
||||
{
|
||||
static void getChar(screen_t *this, int *ch, int *attr, int x, int y) {
|
||||
UNUSED(this);
|
||||
ScreenGetChar(ch,attr,x,y);
|
||||
ScreenGetChar(ch, attr, x, y);
|
||||
}
|
||||
|
||||
|
||||
static int getCursorShape(const screen_t *this)
|
||||
{
|
||||
static int getCursorShape(const screen_t *this) {
|
||||
UNUSED(this);
|
||||
return _farpeekw(dossel, 0x460);
|
||||
}
|
||||
|
||||
|
||||
static void setCursorShape(screen_t *this, int shape)
|
||||
{
|
||||
static void setCursorShape(screen_t *this, int shape) {
|
||||
__dpmi_regs r;
|
||||
|
||||
memset(&r,0,sizeof(r)); /* just in case... */
|
||||
memset(&r, 0, sizeof(r)); /* just in case... */
|
||||
r.x.ax = 0x0103;
|
||||
#if 1
|
||||
if (this)
|
||||
r.h.al = getMode(this); /* required for buggy BIOSes */
|
||||
r.h.al = getMode(this); /* required for buggy BIOSes */
|
||||
#endif
|
||||
r.x.cx = shape & 0x7f1f;
|
||||
__dpmi_int(0x10, &r);
|
||||
}
|
||||
|
||||
|
||||
static int hideCursor(screen_t *this)
|
||||
{
|
||||
static int hideCursor(screen_t *this) {
|
||||
int shape = getCursorShape(this);
|
||||
setCursorShape(this,0x2000);
|
||||
setCursorShape(this, 0x2000);
|
||||
return shape;
|
||||
}
|
||||
|
||||
|
||||
static int init(screen_t *this, int fd)
|
||||
{
|
||||
static int init(screen_t *this, int fd) {
|
||||
int mode;
|
||||
int cols, rows;
|
||||
int attr;
|
||||
@@ -304,7 +243,7 @@ static int init(screen_t *this, int fd)
|
||||
return -1;
|
||||
|
||||
this->data->mode = -1;
|
||||
#ifdef USE_SCROLLBACK
|
||||
#if USE_SCROLLBACK
|
||||
this->data->sb_size = 32;
|
||||
this->data->sb_base = 0;
|
||||
this->data->sb_sp = 0;
|
||||
@@ -314,7 +253,7 @@ static int init(screen_t *this, int fd)
|
||||
if (getPage(this) != 0)
|
||||
return -1;
|
||||
|
||||
#if 1 && defined(__DJGPP__)
|
||||
#if 1 && (ACC_OS_DOS32) && defined(__DJGPP__)
|
||||
/* check for Windows NT/2000/XP */
|
||||
if (_get_dos_version(1) == 0x0532)
|
||||
return -1;
|
||||
@@ -323,27 +262,23 @@ static int init(screen_t *this, int fd)
|
||||
cols = ScreenCols();
|
||||
rows = ScreenRows();
|
||||
mode = getMode(this);
|
||||
if (mode > 0x13)
|
||||
{
|
||||
if (mode > 0x13) {
|
||||
/* assume this is some SVGA/VESA text mode */
|
||||
__dpmi_regs r;
|
||||
|
||||
memset(&r,0,sizeof(r)); /* just in case... */
|
||||
r.x.ax = 0x4f03; /* VESA - get current video mode */
|
||||
memset(&r, 0, sizeof(r)); /* just in case... */
|
||||
r.x.ax = 0x4f03; /* VESA - get current video mode */
|
||||
__dpmi_int(0x10, &r);
|
||||
if (r.h.ah == 0)
|
||||
mode = r.x.bx;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (mode != 2 && mode != 3 && mode != 7)
|
||||
return -1;
|
||||
}
|
||||
ScreenGetCursor(&this->data->cursor_y,&this->data->cursor_x);
|
||||
getChar(this,NULL,&attr,this->data->cursor_x,this->data->cursor_y);
|
||||
ScreenGetCursor(&this->data->cursor_y, &this->data->cursor_x);
|
||||
getChar(this, nullptr, &attr, this->data->cursor_x, this->data->cursor_y);
|
||||
this->data->init_attr = attr;
|
||||
if (mode != 7)
|
||||
{
|
||||
if (mode != 7) {
|
||||
/* Does it normally blink when bg has its 3rd bit set? */
|
||||
int b_mask = (_farpeekb(dossel, 0x465) & 0x20) ? 0x70 : 0xf0;
|
||||
attr = attr & (mask_fg | b_mask);
|
||||
@@ -353,27 +288,22 @@ static int init(screen_t *this, int fd)
|
||||
this->data->rows = rows;
|
||||
this->data->attr = attr;
|
||||
this->data->empty_attr = attr;
|
||||
this->data->empty_cell = make_cell(this,' ',attr);
|
||||
this->data->empty_cell = make_cell(this, ' ', attr);
|
||||
|
||||
ae.cursor_shape = getCursorShape(this);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void updateLineN(screen_t *this, const void *line, int y, int len)
|
||||
{
|
||||
if (y >= 0 && y < this->data->rows && len > 0 && len <= 2*this->data->cols)
|
||||
movedata(_my_ds(),(unsigned)line,dossel,co80+y*this->data->cols*2,len);
|
||||
static void updateLineN(screen_t *this, const void *line, int y, int len) {
|
||||
if (y >= 0 && y < this->data->rows && len > 0 && len <= 2 * this->data->cols)
|
||||
movedata(_my_ds(), (unsigned) line, dossel, co80 + y * this->data->cols * 2, len);
|
||||
}
|
||||
|
||||
|
||||
static void clearLine(screen_t *this, int y)
|
||||
{
|
||||
if (y >= 0 && y < this->data->rows)
|
||||
{
|
||||
static void clearLine(screen_t *this, int y) {
|
||||
if (y >= 0 && y < this->data->rows) {
|
||||
unsigned sp = co80 + y * this->data->cols * 2;
|
||||
unsigned short a = this->data->empty_cell;
|
||||
Cell a = this->data->empty_cell;
|
||||
int i = this->data->cols;
|
||||
|
||||
_farsetsel(dossel);
|
||||
@@ -384,51 +314,43 @@ static void clearLine(screen_t *this, int y)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void clear(screen_t *this)
|
||||
{
|
||||
static void clear(screen_t *this) {
|
||||
unsigned char attr = ScreenAttrib;
|
||||
ScreenAttrib = this->data->empty_attr;
|
||||
ScreenClear();
|
||||
ScreenAttrib = attr;
|
||||
}
|
||||
|
||||
|
||||
static int scrollUp(screen_t *this, int lines)
|
||||
{
|
||||
static int scrollUp(screen_t *this, int lines) {
|
||||
int sr = this->data->rows;
|
||||
int sc = this->data->cols;
|
||||
int y;
|
||||
|
||||
|
||||
if (lines <= 0 || lines > sr)
|
||||
return 0;
|
||||
|
||||
#ifdef USE_SCROLLBACK
|
||||
#if USE_SCROLLBACK
|
||||
/* copy to scrollback buffer */
|
||||
for (y = 0; y < lines; y++)
|
||||
{
|
||||
unsigned short buf[ sc ];
|
||||
movedata(dossel,co80+y*this->data->cols*2,_my_ds(),(unsigned)buf,sizeof(buf));
|
||||
sb_push(this,buf,sizeof(buf));
|
||||
for (y = 0; y < lines; y++) {
|
||||
Cell buf[sc];
|
||||
movedata(dossel, co80 + y * this->data->cols * 2, _my_ds(), (unsigned) buf, sizeof(buf));
|
||||
sb_push(this, buf, sizeof(buf));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* move screen up */
|
||||
if (lines < sr)
|
||||
movedata(dossel,co80+lines*sc*2,dossel,co80,(sr-lines)*sc*2);
|
||||
movedata(dossel, co80 + lines * sc * 2, dossel, co80, (sr - lines) * sc * 2);
|
||||
|
||||
/* fill in blank lines at bottom */
|
||||
for (y = sr - lines; y < sr; y++)
|
||||
clearLine(this,y);
|
||||
clearLine(this, y);
|
||||
|
||||
this->data->scroll_counter += lines;
|
||||
return lines;
|
||||
}
|
||||
|
||||
|
||||
static int scrollDown(screen_t *this, int lines)
|
||||
{
|
||||
static int scrollDown(screen_t *this, int lines) {
|
||||
int sr = this->data->rows;
|
||||
int sc = this->data->cols;
|
||||
int y;
|
||||
@@ -437,26 +359,24 @@ static int scrollDown(screen_t *this, int lines)
|
||||
return 0;
|
||||
|
||||
/* move screen down */
|
||||
if (lines < sr)
|
||||
{
|
||||
if (lines < sr) {
|
||||
/* !@#% movedata can't handle overlapping regions... */
|
||||
/* movedata(dossel,co80,dossel,co80+lines*sc*2,(sr-lines)*sc*2); */
|
||||
unsigned short buf[ (sr-lines)*sc ];
|
||||
movedata(dossel,co80,_my_ds(),(unsigned)buf,sizeof(buf));
|
||||
movedata(_my_ds(),(unsigned)buf,dossel,co80+lines*sc*2,sizeof(buf));
|
||||
Cell buf[(sr - lines) * sc];
|
||||
movedata(dossel, co80, _my_ds(), (unsigned) buf, sizeof(buf));
|
||||
movedata(_my_ds(), (unsigned) buf, dossel, co80 + lines * sc * 2, sizeof(buf));
|
||||
}
|
||||
|
||||
/* copy top lines from scrollback buffer */
|
||||
for (y = lines; --y >= 0; )
|
||||
{
|
||||
#ifdef USE_SCROLLBACK
|
||||
const unsigned short *buf = sb_pop(this);
|
||||
if (buf == NULL)
|
||||
clearLine(this,y);
|
||||
for (y = lines; --y >= 0;) {
|
||||
#if USE_SCROLLBACK
|
||||
const Cell *buf = sb_pop(this);
|
||||
if (buf == nullptr)
|
||||
clearLine(this, y);
|
||||
else
|
||||
updateLineN(this,buf,y,sc*2);
|
||||
updateLineN(this, buf, y, sc * 2);
|
||||
#else
|
||||
clearLine(this,y);
|
||||
clearLine(this, y);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -464,24 +384,16 @@ static int scrollDown(screen_t *this, int lines)
|
||||
return lines;
|
||||
}
|
||||
|
||||
static int getScrollCounter(const screen_t *this) { return this->data->scroll_counter; }
|
||||
|
||||
static int getScrollCounter(const screen_t *this)
|
||||
{
|
||||
return this->data->scroll_counter;
|
||||
}
|
||||
|
||||
|
||||
static int s_kbhit(screen_t *this)
|
||||
{
|
||||
static int s_kbhit(screen_t *this) {
|
||||
UNUSED(this);
|
||||
return kbhit();
|
||||
}
|
||||
|
||||
|
||||
static int intro(screen_t *this, void (*show_frames)(screen_t *) )
|
||||
{
|
||||
static int intro(screen_t *this, void (*show_frames)(screen_t *)) {
|
||||
int shape;
|
||||
unsigned short old_flags = __djgpp_hwint_flags;
|
||||
upx_uint16_t old_flags = __djgpp_hwint_flags;
|
||||
|
||||
if ((this->data->init_attr & mask_bg) != BG_BLACK)
|
||||
return 0;
|
||||
@@ -492,7 +404,7 @@ static int intro(screen_t *this, void (*show_frames)(screen_t *) )
|
||||
|
||||
shape = hideCursor(this);
|
||||
show_frames(this);
|
||||
setCursorShape(this,shape);
|
||||
setCursorShape(this, shape);
|
||||
|
||||
while (kbhit())
|
||||
(void) getkey();
|
||||
@@ -501,65 +413,30 @@ static int intro(screen_t *this, void (*show_frames)(screen_t *) )
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void atExit(void)
|
||||
{
|
||||
static void atExit(void) {
|
||||
static int done = 0;
|
||||
if (done) return;
|
||||
if (done)
|
||||
return;
|
||||
done = 1;
|
||||
if (ae.cursor_shape >= 0)
|
||||
setCursorShape(NULL,ae.cursor_shape);
|
||||
setCursorShape(nullptr, ae.cursor_shape);
|
||||
}
|
||||
|
||||
|
||||
static const screen_t driver =
|
||||
{
|
||||
sobject_destroy,
|
||||
0, /* finalize, */
|
||||
atExit,
|
||||
init,
|
||||
refresh,
|
||||
getMode,
|
||||
getPage,
|
||||
getRows,
|
||||
getCols,
|
||||
isMono,
|
||||
getFg,
|
||||
getBg,
|
||||
getCursor,
|
||||
getCursorShape,
|
||||
setFg,
|
||||
setBg,
|
||||
setCursor,
|
||||
setCursorShape,
|
||||
hideCursor,
|
||||
putChar,
|
||||
putCharAttr,
|
||||
putString,
|
||||
putStringAttr,
|
||||
clear,
|
||||
clearLine,
|
||||
updateLineN,
|
||||
scrollUp,
|
||||
scrollDown,
|
||||
getScrollCounter,
|
||||
s_kbhit,
|
||||
intro,
|
||||
(struct screen_data_t *) 0
|
||||
};
|
||||
|
||||
static const screen_t driver = {sobject_destroy, nullptr, /* finalize */
|
||||
atExit, init, refresh,
|
||||
getMode, getPage, getRows,
|
||||
getCols, isMono, getFg,
|
||||
getBg, getCursor, getCursorShape,
|
||||
setFg, setBg, setCursor,
|
||||
setCursorShape, hideCursor, putChar,
|
||||
putCharAttr, putString, putStringAttr,
|
||||
clear, clearLine, updateLineN,
|
||||
scrollUp, scrollDown, getScrollCounter,
|
||||
s_kbhit, intro, (struct screen_data_t *) nullptr};
|
||||
|
||||
/* public constructor */
|
||||
screen_t *screen_djgpp2_construct(void)
|
||||
{
|
||||
return sobject_construct(&driver,sizeof(*driver.data));
|
||||
}
|
||||
screen_t *screen_djgpp2_construct(void) { return sobject_construct(&driver, sizeof(*driver.data)); }
|
||||
|
||||
#endif /* (USE_SCREEN) && (ACC_OS_DOS32) && defined(__DJGPP__) */
|
||||
|
||||
#endif /* defined(USE_SCREEN) && defined(__DJGPP__) */
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,80 +22,64 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../conf.h"
|
||||
|
||||
#include "conf.h"
|
||||
#if (USE_SCREEN)
|
||||
|
||||
#if defined(USE_SCREEN)
|
||||
|
||||
#define this local_this
|
||||
#define this self
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
// ugly hacks
|
||||
static screen_t *last_screen = NULL;
|
||||
static screen_t *last_screen = nullptr;
|
||||
|
||||
screen_t *sobject_get_screen(void)
|
||||
{
|
||||
return last_screen;
|
||||
}
|
||||
screen_t *sobject_get_screen(void) { return last_screen; }
|
||||
|
||||
|
||||
void sobject_destroy(screen_t *this)
|
||||
{
|
||||
last_screen = NULL;
|
||||
void sobject_destroy(screen_t *this) {
|
||||
last_screen = nullptr;
|
||||
if (!this)
|
||||
return;
|
||||
if (this->data)
|
||||
{
|
||||
if (this->data) {
|
||||
if (this->finalize)
|
||||
this->finalize(this);
|
||||
free(this->data);
|
||||
this->data = NULL;
|
||||
this->data = nullptr;
|
||||
}
|
||||
free(this);
|
||||
}
|
||||
|
||||
|
||||
screen_t *sobject_construct(const screen_t *c, size_t data_size)
|
||||
{
|
||||
screen_t *sobject_construct(const screen_t *c, size_t data_size) {
|
||||
screen_t *this;
|
||||
|
||||
last_screen = NULL;
|
||||
last_screen = nullptr;
|
||||
|
||||
/* allocate object */
|
||||
this = (screen_t *) malloc(sizeof(*this));
|
||||
if (!this)
|
||||
return NULL;
|
||||
return nullptr;
|
||||
|
||||
/* copy function table */
|
||||
*this = *c;
|
||||
|
||||
/* initialize instance variables */
|
||||
this->data = (struct screen_data_t *) malloc(data_size);
|
||||
if (!this->data)
|
||||
{
|
||||
if (!this->data) {
|
||||
free(this);
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
memset(this->data,0,data_size);
|
||||
memset(this->data, 0, data_size);
|
||||
|
||||
last_screen = this;
|
||||
return this;
|
||||
}
|
||||
|
||||
#endif /* (USE_SCREEN) */
|
||||
|
||||
#endif /* defined(USE_SCREEN) */
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,23 +22,21 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../conf.h"
|
||||
|
||||
#include "conf.h"
|
||||
|
||||
#if defined(USE_SCREEN) && defined(USE_SCREEN_VCSA)
|
||||
#if (USE_SCREEN) && (USE_SCREEN_VCSA)
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
#define this local_this
|
||||
#define this self
|
||||
|
||||
#define mask_fg 0x0f
|
||||
#define mask_bg 0xf0
|
||||
|
||||
/* #define USE_SCROLLBACK */
|
||||
|
||||
/* #define USE_SCROLLBACK 1 */
|
||||
|
||||
/*************************************************************************
|
||||
// direct screen access ( /dev/vcsaNN )
|
||||
@@ -48,14 +46,14 @@
|
||||
#include <sys/select.h>
|
||||
#include <termios.h>
|
||||
#if defined(__linux__)
|
||||
# include <linux/kd.h>
|
||||
# include <linux/kdev_t.h>
|
||||
# include <linux/major.h>
|
||||
#include <linux/kd.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/major.h>
|
||||
#endif
|
||||
|
||||
#define Cell upx_uint16_t
|
||||
|
||||
struct screen_data_t
|
||||
{
|
||||
struct screen_data_t {
|
||||
int fd;
|
||||
int mode;
|
||||
int page;
|
||||
@@ -67,129 +65,81 @@ struct screen_data_t
|
||||
unsigned char attr;
|
||||
unsigned char init_attr;
|
||||
unsigned char map[256];
|
||||
unsigned short empty_line[256];
|
||||
#ifdef USE_SCROLLBACK
|
||||
Cell empty_line[256];
|
||||
#if USE_SCROLLBACK
|
||||
/* scrollback buffer */
|
||||
unsigned short sb_buf[32][256];
|
||||
Cell sb_buf[32][256];
|
||||
int sb_size;
|
||||
int sb_base;
|
||||
int sb_sp;
|
||||
#endif /* USE_SCROLLBACK */
|
||||
};
|
||||
|
||||
|
||||
#ifdef USE_SCROLLBACK
|
||||
static __inline__ void sb_add(screen_t *this, int *val, int inc)
|
||||
{
|
||||
#if USE_SCROLLBACK
|
||||
static __inline__ void sb_add(screen_t *this, int *val, int inc) {
|
||||
*val = (*val + inc) & (this->data->sb_size - 1);
|
||||
}
|
||||
|
||||
static void sb_push(screen_t *this, const unsigned short *line, int len)
|
||||
{
|
||||
memcpy(this->data->sb_buf[this->data->sb_sp],line,len);
|
||||
sb_add(this,&this->data->sb_sp,1);
|
||||
static void sb_push(screen_t *this, const Cell *line, int len) {
|
||||
memcpy(this->data->sb_buf[this->data->sb_sp], line, len);
|
||||
sb_add(this, &this->data->sb_sp, 1);
|
||||
if (this->data->sb_sp == this->data->sb_base)
|
||||
sb_add(this,&this->data->sb_base,1);
|
||||
sb_add(this, &this->data->sb_base, 1);
|
||||
}
|
||||
|
||||
static const unsigned short *sb_pop(screen_t *this)
|
||||
{
|
||||
static const Cell *sb_pop(screen_t *this) {
|
||||
if (this->data->sb_sp == this->data->sb_base)
|
||||
return NULL;
|
||||
sb_add(this,&this->data->sb_sp,-1);
|
||||
return nullptr;
|
||||
sb_add(this, &this->data->sb_sp, -1);
|
||||
return this->data->sb_buf[this->data->sb_sp];
|
||||
}
|
||||
#endif /* USE_SCROLLBACK */
|
||||
|
||||
static void refresh(screen_t *this) { UNUSED(this); }
|
||||
|
||||
static void refresh(screen_t *this)
|
||||
{
|
||||
UNUSED(this);
|
||||
}
|
||||
|
||||
|
||||
static __inline__
|
||||
unsigned short make_cell(screen_t *this, int ch, int attr)
|
||||
{
|
||||
static __inline__ Cell make_cell(screen_t *this, int ch, int attr) {
|
||||
return ((attr & 0xff) << 8) | (this->data->map[ch & 0xff] & 0xff);
|
||||
}
|
||||
|
||||
static int getMode(const screen_t *this) { return this->data->mode; }
|
||||
|
||||
static int getMode(const screen_t *this)
|
||||
{
|
||||
return this->data->mode;
|
||||
}
|
||||
static int getPage(const screen_t *this) { return this->data->page; }
|
||||
|
||||
static int getRows(const screen_t *this) { return this->data->rows; }
|
||||
|
||||
static int getPage(const screen_t *this)
|
||||
{
|
||||
return this->data->page;
|
||||
}
|
||||
static int getCols(const screen_t *this) { return this->data->cols; }
|
||||
|
||||
|
||||
static int getRows(const screen_t *this)
|
||||
{
|
||||
return this->data->rows;
|
||||
}
|
||||
|
||||
|
||||
static int getCols(const screen_t *this)
|
||||
{
|
||||
return this->data->cols;
|
||||
}
|
||||
|
||||
|
||||
static int isMono(const screen_t *this)
|
||||
{
|
||||
static int isMono(const screen_t *this) {
|
||||
/* FIXME */
|
||||
UNUSED(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getFg(const screen_t *this) { return this->data->attr & mask_fg; }
|
||||
|
||||
static int getFg(const screen_t *this)
|
||||
{
|
||||
return this->data->attr & mask_fg;
|
||||
}
|
||||
static int getBg(const screen_t *this) { return this->data->attr & mask_bg; }
|
||||
|
||||
|
||||
static int getBg(const screen_t *this)
|
||||
{
|
||||
return this->data->attr & mask_bg;
|
||||
}
|
||||
|
||||
|
||||
static void setFg(screen_t *this, int fg)
|
||||
{
|
||||
static void setFg(screen_t *this, int fg) {
|
||||
this->data->attr = (this->data->attr & mask_bg) | (fg & mask_fg);
|
||||
}
|
||||
|
||||
|
||||
static void setBg(screen_t *this, int bg)
|
||||
{
|
||||
static void setBg(screen_t *this, int bg) {
|
||||
this->data->attr = (this->data->attr & mask_fg) | (bg & mask_bg);
|
||||
}
|
||||
|
||||
|
||||
/* private */
|
||||
static int gotoxy(screen_t *this, int x, int y)
|
||||
{
|
||||
if (x >= 0 && y >= 0 && x < this->data->cols && y < this->data->rows)
|
||||
{
|
||||
if (lseek(this->data->fd, 4 + (x + y * this->data->cols) * 2, SEEK_SET) != -1)
|
||||
{
|
||||
static int gotoxy(screen_t *this, int x, int y) {
|
||||
if (x >= 0 && y >= 0 && x < this->data->cols && y < this->data->rows) {
|
||||
if (lseek(this->data->fd, 4 + (x + y * this->data->cols) * 2, SEEK_SET) != -1) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static void setCursor(screen_t *this, int x, int y)
|
||||
{
|
||||
if (gotoxy(this,x,y) == 0)
|
||||
{
|
||||
unsigned char b[2] = { x, y };
|
||||
static void setCursor(screen_t *this, int x, int y) {
|
||||
if (gotoxy(this, x, y) == 0) {
|
||||
unsigned char b[2] = {x, y};
|
||||
if (lseek(this->data->fd, 2, SEEK_SET) != -1)
|
||||
write(this->data->fd, b, 2);
|
||||
this->data->cursor_x = x;
|
||||
@@ -197,67 +147,53 @@ static void setCursor(screen_t *this, int x, int y)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void getCursor(const screen_t *this, int *x, int *y)
|
||||
{
|
||||
static void getCursor(const screen_t *this, int *x, int *y) {
|
||||
int cx = this->data->cursor_x;
|
||||
int cy = this->data->cursor_y;
|
||||
#if 1
|
||||
if (lseek(this->data->fd, 2, SEEK_SET) != -1)
|
||||
{
|
||||
if (lseek(this->data->fd, 2, SEEK_SET) != -1) {
|
||||
unsigned char b[2];
|
||||
if (read(this->data->fd, b, 2) == 2)
|
||||
{
|
||||
if (b[0] < this->data->cols && b[1] < this->data->rows)
|
||||
{
|
||||
if (read(this->data->fd, b, 2) == 2) {
|
||||
if (b[0] < this->data->cols && b[1] < this->data->rows) {
|
||||
cx = b[0];
|
||||
cy = b[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (x) *x = cx;
|
||||
if (y) *y = cy;
|
||||
if (x)
|
||||
*x = cx;
|
||||
if (y)
|
||||
*y = cy;
|
||||
}
|
||||
|
||||
static void putCharAttr(screen_t *this, int ch, int attr, int x, int y) {
|
||||
Cell a = make_cell(this, ch, attr);
|
||||
|
||||
static void putCharAttr(screen_t *this, int ch, int attr, int x, int y)
|
||||
{
|
||||
unsigned short a = make_cell(this,ch,attr);
|
||||
|
||||
if (gotoxy(this,x,y) == 0)
|
||||
if (gotoxy(this, x, y) == 0)
|
||||
write(this->data->fd, &a, 2);
|
||||
}
|
||||
|
||||
|
||||
static void putChar(screen_t *this, int ch, int x, int y)
|
||||
{
|
||||
putCharAttr(this,ch,this->data->attr,x,y);
|
||||
static void putChar(screen_t *this, int ch, int x, int y) {
|
||||
putCharAttr(this, ch, this->data->attr, x, y);
|
||||
}
|
||||
|
||||
|
||||
static void putStringAttr(screen_t *this, const char *s, int attr, int x, int y)
|
||||
{
|
||||
assert((int)strlen(s) <= 256);
|
||||
assert(x + (int)strlen(s) <= this->data->cols);
|
||||
static void putStringAttr(screen_t *this, const char *s, int attr, int x, int y) {
|
||||
assert((int) strlen(s) <= 256);
|
||||
assert(x + (int) strlen(s) <= this->data->cols);
|
||||
while (*s)
|
||||
putCharAttr(this,*s++,attr,x++,y);
|
||||
putCharAttr(this, *s++, attr, x++, y);
|
||||
}
|
||||
|
||||
|
||||
static void putString(screen_t *this, const char *s, int x, int y)
|
||||
{
|
||||
putStringAttr(this,s,this->data->attr,x,y);
|
||||
static void putString(screen_t *this, const char *s, int x, int y) {
|
||||
putStringAttr(this, s, this->data->attr, x, y);
|
||||
}
|
||||
|
||||
|
||||
/* private */
|
||||
static void getChar(screen_t *this, int *ch, int *attr, int x, int y)
|
||||
{
|
||||
unsigned short a;
|
||||
static void getChar(screen_t *this, int *ch, int *attr, int x, int y) {
|
||||
upx_uint16_t a;
|
||||
|
||||
if (gotoxy(this,x,y) == 0 && read(this->data->fd, &a, 2) == 2)
|
||||
{
|
||||
if (gotoxy(this, x, y) == 0 && read(this->data->fd, &a, 2) == 2) {
|
||||
if (ch)
|
||||
*ch = a & 0xff;
|
||||
if (attr)
|
||||
@@ -265,19 +201,15 @@ static void getChar(screen_t *this, int *ch, int *attr, int x, int y)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* private */
|
||||
static int init_scrnmap(screen_t *this, int fd)
|
||||
{
|
||||
static int init_scrnmap(screen_t *this, int fd) {
|
||||
int scrnmap_done = 0;
|
||||
int i;
|
||||
|
||||
#if 1 && defined(GIO_UNISCRNMAP) && defined(E_TABSZ)
|
||||
if (!scrnmap_done)
|
||||
{
|
||||
unsigned short scrnmap[E_TABSZ];
|
||||
if (ioctl(fd, GIO_UNISCRNMAP, scrnmap) == 0)
|
||||
{
|
||||
if (!scrnmap_done) {
|
||||
upx_uint16_t scrnmap[E_TABSZ];
|
||||
if (ioctl(fd, GIO_UNISCRNMAP, scrnmap) == 0) {
|
||||
for (i = 0; i < E_TABSZ; i++)
|
||||
this->data->map[scrnmap[i] & 0xff] = i;
|
||||
scrnmap_done = 1;
|
||||
@@ -285,11 +217,9 @@ static int init_scrnmap(screen_t *this, int fd)
|
||||
}
|
||||
#endif
|
||||
#if 1 && defined(GIO_SCRNMAP) && defined(E_TABSZ)
|
||||
if (!scrnmap_done)
|
||||
{
|
||||
if (!scrnmap_done) {
|
||||
unsigned char scrnmap[E_TABSZ];
|
||||
if (ioctl(fd, GIO_SCRNMAP, scrnmap) == 0)
|
||||
{
|
||||
if (ioctl(fd, GIO_SCRNMAP, scrnmap) == 0) {
|
||||
for (i = 0; i < E_TABSZ; i++)
|
||||
this->data->map[scrnmap[i] & 0xff] = i;
|
||||
scrnmap_done = 1;
|
||||
@@ -300,9 +230,7 @@ static int init_scrnmap(screen_t *this, int fd)
|
||||
return scrnmap_done;
|
||||
}
|
||||
|
||||
|
||||
static int init(screen_t *this, int fd)
|
||||
{
|
||||
static int init(screen_t *this, int fd) {
|
||||
struct stat st;
|
||||
|
||||
if (!this || !this->data)
|
||||
@@ -311,37 +239,33 @@ static int init(screen_t *this, int fd)
|
||||
this->data->fd = -1;
|
||||
this->data->mode = -1;
|
||||
this->data->page = 0;
|
||||
#ifdef USE_SCROLLBACK
|
||||
#if USE_SCROLLBACK
|
||||
this->data->sb_size = 32;
|
||||
this->data->sb_base = 0;
|
||||
this->data->sb_sp = 0;
|
||||
#endif
|
||||
if (fd < 0 || !acc_isatty(fd))
|
||||
return -1;
|
||||
if (fstat(fd,&st) != 0)
|
||||
if (fstat(fd, &st) != 0)
|
||||
return -1;
|
||||
|
||||
/* check if we are running in a virtual console */
|
||||
/* check if we are running in a virtual console */
|
||||
#if defined(MINOR) && defined(MAJOR) && defined(TTY_MAJOR)
|
||||
if (MAJOR(st.st_rdev) == TTY_MAJOR)
|
||||
{
|
||||
if (MAJOR(st.st_rdev) == TTY_MAJOR) {
|
||||
char vc_name[64];
|
||||
unsigned char vc_data[4];
|
||||
int i;
|
||||
int attr;
|
||||
unsigned short a;
|
||||
Cell a;
|
||||
|
||||
upx_snprintf(vc_name, sizeof(vc_name), "/dev/vcsa%d", (int) MINOR(st.st_rdev));
|
||||
upx_safe_snprintf(vc_name, sizeof(vc_name), "/dev/vcsa%d", (int) MINOR(st.st_rdev));
|
||||
this->data->fd = open(vc_name, O_RDWR);
|
||||
if (this->data->fd == -1)
|
||||
{
|
||||
upx_snprintf(vc_name, sizeof(vc_name), "/dev/vcc/a%d", (int) MINOR(st.st_rdev));
|
||||
if (this->data->fd == -1) {
|
||||
upx_safe_snprintf(vc_name, sizeof(vc_name), "/dev/vcc/a%d", (int) MINOR(st.st_rdev));
|
||||
this->data->fd = open(vc_name, O_RDWR);
|
||||
}
|
||||
if (this->data->fd != -1)
|
||||
{
|
||||
if (read(this->data->fd, vc_data, 4) == 4)
|
||||
{
|
||||
if (this->data->fd != -1) {
|
||||
if (read(this->data->fd, vc_data, 4) == 4) {
|
||||
this->data->mode = 3;
|
||||
this->data->rows = vc_data[0];
|
||||
this->data->cols = vc_data[1];
|
||||
@@ -350,18 +274,15 @@ static int init(screen_t *this, int fd)
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
this->data->map[i] = i;
|
||||
i = init_scrnmap(this,this->data->fd) ||
|
||||
init_scrnmap(this,STDIN_FILENO);
|
||||
i = init_scrnmap(this, this->data->fd) || init_scrnmap(this, STDIN_FILENO);
|
||||
|
||||
getChar(this,NULL,&attr,this->data->cursor_x,this->data->cursor_y);
|
||||
getChar(this, nullptr, &attr, this->data->cursor_x, this->data->cursor_y);
|
||||
this->data->init_attr = attr;
|
||||
this->data->attr = attr;
|
||||
a = make_cell(this,' ',attr);
|
||||
a = make_cell(this, ' ', attr);
|
||||
for (i = 0; i < 256; i++)
|
||||
this->data->empty_line[i] = a;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
close(this->data->fd);
|
||||
this->data->fd = -1;
|
||||
}
|
||||
@@ -375,25 +296,19 @@ static int init(screen_t *this, int fd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void finalize(screen_t *this)
|
||||
{
|
||||
static void finalize(screen_t *this) {
|
||||
if (this->data->fd != -1)
|
||||
(void) close(this->data->fd);
|
||||
}
|
||||
|
||||
|
||||
static void updateLineN(screen_t *this, const void *line, int y, int len)
|
||||
{
|
||||
if (len > 0 && len <= 2*this->data->cols && gotoxy(this,0,y) == 0)
|
||||
{
|
||||
static void updateLineN(screen_t *this, const void *line, int y, int len) {
|
||||
if (len > 0 && len <= 2 * this->data->cols && gotoxy(this, 0, y) == 0) {
|
||||
int i;
|
||||
unsigned char new_line[len];
|
||||
unsigned char *l1 = new_line;
|
||||
const unsigned char *l2 = (const unsigned char *) line;
|
||||
|
||||
for (i = 0; i < len; i += 2)
|
||||
{
|
||||
for (i = 0; i < len; i += 2) {
|
||||
*l1++ = *l2++;
|
||||
*l1++ = this->data->map[*l2++];
|
||||
}
|
||||
@@ -401,25 +316,19 @@ static void updateLineN(screen_t *this, const void *line, int y, int len)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void clearLine(screen_t *this, int y)
|
||||
{
|
||||
if (gotoxy(this,0,y) == 0)
|
||||
write(this->data->fd, this->data->empty_line, 2*this->data->cols);
|
||||
static void clearLine(screen_t *this, int y) {
|
||||
if (gotoxy(this, 0, y) == 0)
|
||||
write(this->data->fd, this->data->empty_line, 2 * this->data->cols);
|
||||
}
|
||||
|
||||
|
||||
static void clear(screen_t *this)
|
||||
{
|
||||
static void clear(screen_t *this) {
|
||||
int y;
|
||||
|
||||
for (y = 0; y < this->data->rows; y++)
|
||||
clearLine(this,y);
|
||||
clearLine(this, y);
|
||||
}
|
||||
|
||||
|
||||
static int scrollUp(screen_t *this, int lines)
|
||||
{
|
||||
static int scrollUp(screen_t *this, int lines) {
|
||||
int sr = this->data->rows;
|
||||
int sc = this->data->cols;
|
||||
int y;
|
||||
@@ -427,38 +336,34 @@ static int scrollUp(screen_t *this, int lines)
|
||||
if (lines <= 0 || lines > sr)
|
||||
return 0;
|
||||
|
||||
#ifdef USE_SCROLLBACK
|
||||
#if USE_SCROLLBACK
|
||||
/* copy to scrollback buffer */
|
||||
for (y = 0; y < lines; y++)
|
||||
{
|
||||
unsigned short buf[ sc ];
|
||||
gotoxy(this,0,y);
|
||||
for (y = 0; y < lines; y++) {
|
||||
Cell buf[sc];
|
||||
gotoxy(this, 0, y);
|
||||
read(this->data->fd, buf, sizeof(buf));
|
||||
sb_push(this,buf,sizeof(buf));
|
||||
sb_push(this, buf, sizeof(buf));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* move screen up */
|
||||
if (lines < sr)
|
||||
{
|
||||
unsigned short buf[ (sr-lines)*sc ];
|
||||
gotoxy(this,0,lines);
|
||||
if (lines < sr) {
|
||||
Cell buf[(sr - lines) * sc];
|
||||
gotoxy(this, 0, lines);
|
||||
read(this->data->fd, buf, sizeof(buf));
|
||||
gotoxy(this,0,0);
|
||||
gotoxy(this, 0, 0);
|
||||
write(this->data->fd, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
/* fill in blank lines at bottom */
|
||||
for (y = sr - lines; y < sr; y++)
|
||||
clearLine(this,y);
|
||||
clearLine(this, y);
|
||||
|
||||
this->data->scroll_counter += lines;
|
||||
return lines;
|
||||
}
|
||||
|
||||
|
||||
static int scrollDown(screen_t *this, int lines)
|
||||
{
|
||||
static int scrollDown(screen_t *this, int lines) {
|
||||
int sr = this->data->rows;
|
||||
int sc = this->data->cols;
|
||||
int y;
|
||||
@@ -467,26 +372,24 @@ static int scrollDown(screen_t *this, int lines)
|
||||
return 0;
|
||||
|
||||
/* move screen down */
|
||||
if (lines < sr)
|
||||
{
|
||||
unsigned short buf[ (sr-lines)*sc ];
|
||||
gotoxy(this,0,0);
|
||||
if (lines < sr) {
|
||||
Cell buf[(sr - lines) * sc];
|
||||
gotoxy(this, 0, 0);
|
||||
read(this->data->fd, buf, sizeof(buf));
|
||||
gotoxy(this,0,lines);
|
||||
gotoxy(this, 0, lines);
|
||||
write(this->data->fd, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
/* copy top lines from scrollback buffer */
|
||||
for (y = lines; --y >= 0; )
|
||||
{
|
||||
#ifdef USE_SCROLLBACK
|
||||
const unsigned short *buf = sb_pop(this);
|
||||
if (buf == NULL)
|
||||
clearLine(this,y);
|
||||
for (y = lines; --y >= 0;) {
|
||||
#if USE_SCROLLBACK
|
||||
const Cell *buf = sb_pop(this);
|
||||
if (buf == nullptr)
|
||||
clearLine(this, y);
|
||||
else
|
||||
updateLineN(this,buf,y,sc*2);
|
||||
updateLineN(this, buf, y, sc * 2);
|
||||
#else
|
||||
clearLine(this,y);
|
||||
clearLine(this, y);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -494,45 +397,33 @@ static int scrollDown(screen_t *this, int lines)
|
||||
return lines;
|
||||
}
|
||||
|
||||
static int getScrollCounter(const screen_t *this) { return this->data->scroll_counter; }
|
||||
|
||||
static int getScrollCounter(const screen_t *this)
|
||||
{
|
||||
return this->data->scroll_counter;
|
||||
}
|
||||
|
||||
|
||||
static int getCursorShape(const screen_t *this)
|
||||
{
|
||||
static int getCursorShape(const screen_t *this) {
|
||||
UNUSED(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void setCursorShape(screen_t *this, int shape)
|
||||
{
|
||||
static void setCursorShape(screen_t *this, int shape) {
|
||||
UNUSED(this);
|
||||
UNUSED(shape);
|
||||
}
|
||||
|
||||
|
||||
static int kbhit(screen_t *this)
|
||||
{
|
||||
static int kbhit(screen_t *this) {
|
||||
const int fd = STDIN_FILENO;
|
||||
const unsigned long usec = 0;
|
||||
const unsigned usec = 0;
|
||||
struct timeval tv;
|
||||
fd_set fds;
|
||||
|
||||
UNUSED(this);
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
tv.tv_sec = usec / 1000000;
|
||||
tv.tv_sec = usec / 1000000;
|
||||
tv.tv_usec = usec % 1000000;
|
||||
return (select(fd + 1, &fds, NULL, NULL, &tv) > 0);
|
||||
return (select(fd + 1, &fds, nullptr, nullptr, &tv) > 0);
|
||||
}
|
||||
|
||||
|
||||
static int intro(screen_t *this, void (*show_frames)(screen_t *) )
|
||||
{
|
||||
static int intro(screen_t *this, void (*show_frames)(screen_t *)) {
|
||||
int shape;
|
||||
struct termios term_old, term_new;
|
||||
int term_r;
|
||||
@@ -541,19 +432,18 @@ static int intro(screen_t *this, void (*show_frames)(screen_t *) )
|
||||
return 0;
|
||||
|
||||
term_r = tcgetattr(STDIN_FILENO, &term_old);
|
||||
if (term_r == 0)
|
||||
{
|
||||
if (term_r == 0) {
|
||||
term_new = term_old;
|
||||
term_new.c_lflag &= ~(ISIG | ICANON | ECHO);
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &term_new);
|
||||
}
|
||||
|
||||
shape = getCursorShape(this);
|
||||
setCursorShape(this,0x2000);
|
||||
setCursorShape(this, 0x2000);
|
||||
show_frames(this);
|
||||
if (this->data->rows > 24)
|
||||
setCursor(this,this->data->cursor_x,this->data->cursor_y+1);
|
||||
setCursorShape(this,shape);
|
||||
setCursor(this, this->data->cursor_x, this->data->cursor_y + 1);
|
||||
setCursorShape(this, shape);
|
||||
|
||||
while (kbhit(this))
|
||||
(void) fgetc(stdin);
|
||||
@@ -563,55 +453,42 @@ static int intro(screen_t *this, void (*show_frames)(screen_t *) )
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const screen_t driver =
|
||||
{
|
||||
sobject_destroy,
|
||||
finalize,
|
||||
0, /* atExit */
|
||||
init,
|
||||
refresh,
|
||||
getMode,
|
||||
getPage,
|
||||
getRows,
|
||||
getCols,
|
||||
isMono,
|
||||
getFg,
|
||||
getBg,
|
||||
getCursor,
|
||||
getCursorShape,
|
||||
setFg,
|
||||
setBg,
|
||||
setCursor,
|
||||
setCursorShape,
|
||||
0, /* hideCursor */
|
||||
putChar,
|
||||
putCharAttr,
|
||||
putString,
|
||||
putStringAttr,
|
||||
clear,
|
||||
clearLine,
|
||||
updateLineN,
|
||||
scrollUp,
|
||||
scrollDown,
|
||||
getScrollCounter,
|
||||
kbhit,
|
||||
intro,
|
||||
(struct screen_data_t *) 0
|
||||
};
|
||||
|
||||
static const screen_t driver = {sobject_destroy,
|
||||
finalize,
|
||||
nullptr, /* atExit */
|
||||
init,
|
||||
refresh,
|
||||
getMode,
|
||||
getPage,
|
||||
getRows,
|
||||
getCols,
|
||||
isMono,
|
||||
getFg,
|
||||
getBg,
|
||||
getCursor,
|
||||
getCursorShape,
|
||||
setFg,
|
||||
setBg,
|
||||
setCursor,
|
||||
setCursorShape,
|
||||
nullptr, /* hideCursor */
|
||||
putChar,
|
||||
putCharAttr,
|
||||
putString,
|
||||
putStringAttr,
|
||||
clear,
|
||||
clearLine,
|
||||
updateLineN,
|
||||
scrollUp,
|
||||
scrollDown,
|
||||
getScrollCounter,
|
||||
kbhit,
|
||||
intro,
|
||||
(struct screen_data_t *) nullptr};
|
||||
|
||||
/* public constructor */
|
||||
screen_t *screen_vcsa_construct(void)
|
||||
{
|
||||
return sobject_construct(&driver,sizeof(*driver.data));
|
||||
}
|
||||
screen_t *screen_vcsa_construct(void) { return sobject_construct(&driver, sizeof(*driver.data)); }
|
||||
|
||||
#endif /* (USE_SCREEN) && (USE_SCREEN_VCSA) */
|
||||
|
||||
#endif /* defined(USE_SCREEN) && defined(USE_SCREEN_VCSA) */
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,43 +22,39 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../conf.h"
|
||||
|
||||
#include "conf.h"
|
||||
|
||||
#if defined(USE_SCREEN_WIN32)
|
||||
#if (USE_SCREEN_WIN32)
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
#define this local_this
|
||||
#define this self
|
||||
|
||||
#define mask_fg 0x0f
|
||||
#define mask_bg 0xf0
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// direct screen access
|
||||
**************************************************************************/
|
||||
|
||||
#if (ACC_CC_MSC && (_MSC_VER >= 1000 && _MSC_VER < 1200))
|
||||
/* avoid -W4 warnings in <conio.h> */
|
||||
# pragma warning(disable: 4032)
|
||||
/* avoid -W4 warnings in <windows.h> */
|
||||
# pragma warning(disable: 4201 4214 4514)
|
||||
/* avoid -W4 warnings in <conio.h> */
|
||||
#pragma warning(disable : 4032)
|
||||
/* avoid -W4 warnings in <windows.h> */
|
||||
#pragma warning(disable : 4201 4214 4514)
|
||||
#endif
|
||||
#if defined(__RSXNT__)
|
||||
# define timeval win32_timeval /* struct timeval already in <sys/time.h> */
|
||||
#define timeval win32_timeval /* struct timeval already in <sys/time.h> */
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#if defined(HAVE_CONIO_H)
|
||||
# include <conio.h>
|
||||
#if (HAVE_CONIO_H)
|
||||
#include <conio.h>
|
||||
#endif
|
||||
|
||||
|
||||
struct screen_data_t
|
||||
{
|
||||
struct screen_data_t {
|
||||
HANDLE hi;
|
||||
HANDLE ho;
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
@@ -80,106 +76,65 @@ struct screen_data_t
|
||||
CHAR_INFO empty_line[256];
|
||||
};
|
||||
|
||||
#define P(x) ((SHORT) (x))
|
||||
|
||||
#define P(x) ((SHORT) (x))
|
||||
|
||||
static const COORD pos00 = { 0, 0 };
|
||||
static const COORD size11 = { 1, 1 };
|
||||
|
||||
static const COORD pos00 = {0, 0};
|
||||
static const COORD size11 = {1, 1};
|
||||
|
||||
/* atExit information */
|
||||
static struct
|
||||
{
|
||||
static struct {
|
||||
int is_valid;
|
||||
HANDLE ho;
|
||||
CONSOLE_CURSOR_INFO cci;
|
||||
} ae;
|
||||
|
||||
static void refresh(screen_t *this) { UNUSED(this); }
|
||||
|
||||
static void refresh(screen_t *this)
|
||||
{
|
||||
UNUSED(this);
|
||||
}
|
||||
static int getMode(const screen_t *this) { return this->data->mode; }
|
||||
|
||||
|
||||
static int getMode(const screen_t *this)
|
||||
{
|
||||
return this->data->mode;
|
||||
}
|
||||
|
||||
|
||||
static int getPage(const screen_t *this)
|
||||
{
|
||||
static int getPage(const screen_t *this) {
|
||||
UNUSED(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getRows(const screen_t *this) { return this->data->rows; }
|
||||
|
||||
static int getRows(const screen_t *this)
|
||||
{
|
||||
return this->data->rows;
|
||||
}
|
||||
static int getCols(const screen_t *this) { return this->data->cols; }
|
||||
|
||||
|
||||
static int getCols(const screen_t *this)
|
||||
{
|
||||
return this->data->cols;
|
||||
}
|
||||
|
||||
|
||||
static int isMono(const screen_t *this)
|
||||
{
|
||||
static int isMono(const screen_t *this) {
|
||||
UNUSED(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getFg(const screen_t *this) { return this->data->attr & mask_fg; }
|
||||
|
||||
static int getFg(const screen_t *this)
|
||||
{
|
||||
return this->data->attr & mask_fg;
|
||||
}
|
||||
static int getBg(const screen_t *this) { return this->data->attr & mask_bg; }
|
||||
|
||||
|
||||
static int getBg(const screen_t *this)
|
||||
{
|
||||
return this->data->attr & mask_bg;
|
||||
}
|
||||
|
||||
|
||||
static void setFg(screen_t *this, int fg)
|
||||
{
|
||||
static void setFg(screen_t *this, int fg) {
|
||||
this->data->attr = (WORD) ((this->data->attr & mask_bg) | (fg & mask_fg));
|
||||
SetConsoleTextAttribute(this->data->ho, this->data->attr);
|
||||
}
|
||||
|
||||
|
||||
static void setBg(screen_t *this, int bg)
|
||||
{
|
||||
static void setBg(screen_t *this, int bg) {
|
||||
this->data->attr = (WORD) ((this->data->attr & mask_fg) | (bg & mask_bg));
|
||||
SetConsoleTextAttribute(this->data->ho, this->data->attr);
|
||||
}
|
||||
|
||||
|
||||
static void setCursor(screen_t *this, int x, int y)
|
||||
{
|
||||
if (x >= 0 && y >= 0 && x < this->data->cols && y < this->data->rows)
|
||||
{
|
||||
COORD coord = { P(x), P(y) };
|
||||
static void setCursor(screen_t *this, int x, int y) {
|
||||
if (x >= 0 && y >= 0 && x < this->data->cols && y < this->data->rows) {
|
||||
COORD coord = {P(x), P(y)};
|
||||
SetConsoleCursorPosition(this->data->ho, coord);
|
||||
this->data->cursor_x = x;
|
||||
this->data->cursor_y = y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void getCursor(const screen_t *this, int *x, int *y)
|
||||
{
|
||||
static void getCursor(const screen_t *this, int *x, int *y) {
|
||||
int cx = this->data->cursor_x;
|
||||
int cy = this->data->cursor_y;
|
||||
#if 1
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
if (GetConsoleScreenBufferInfo(this->data->ho, &csbi))
|
||||
{
|
||||
if (GetConsoleScreenBufferInfo(this->data->ho, &csbi)) {
|
||||
cx = csbi.dwCursorPosition.X;
|
||||
cy = csbi.dwCursorPosition.Y;
|
||||
#if 0
|
||||
@@ -188,30 +143,26 @@ static void getCursor(const screen_t *this, int *x, int *y)
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
if (x) *x = cx;
|
||||
if (y) *y = cy;
|
||||
if (x)
|
||||
*x = cx;
|
||||
if (y)
|
||||
*y = cy;
|
||||
}
|
||||
|
||||
|
||||
static void putCharAttr(screen_t *this, int ch, int attr, int x, int y)
|
||||
{
|
||||
static void putCharAttr(screen_t *this, int ch, int attr, int x, int y) {
|
||||
CHAR_INFO ci;
|
||||
SMALL_RECT region = { P(x), P(y), P(x), P(y) };
|
||||
SMALL_RECT region = {P(x), P(y), P(x), P(y)};
|
||||
ci.Char.UnicodeChar = 0;
|
||||
ci.Char.AsciiChar = (CHAR) ch;
|
||||
ci.Attributes = (WORD) attr;
|
||||
WriteConsoleOutputA(this->data->ho, &ci, size11, pos00, ®ion);
|
||||
}
|
||||
|
||||
|
||||
static void putChar(screen_t *this, int ch, int x, int y)
|
||||
{
|
||||
static void putChar(screen_t *this, int ch, int x, int y) {
|
||||
this->putCharAttr(this, ch, this->data->attr, x, y);
|
||||
}
|
||||
|
||||
|
||||
static void putStringAttr(screen_t *this, const char *s, int attr, int x, int y)
|
||||
{
|
||||
static void putStringAttr(screen_t *this, const char *s, int attr, int x, int y) {
|
||||
int i;
|
||||
int l = (int) strlen(s);
|
||||
if (l <= 0)
|
||||
@@ -219,10 +170,9 @@ static void putStringAttr(screen_t *this, const char *s, int attr, int x, int y)
|
||||
assert(l <= 256);
|
||||
assert(x + l <= this->data->cols);
|
||||
CHAR_INFO ci[256];
|
||||
COORD size = { P(l), 1 };
|
||||
SMALL_RECT region = { P(x), P(y), P(x + l - 1), P(y) };
|
||||
for (i = 0; i < l; i++)
|
||||
{
|
||||
COORD size = {P(l), 1};
|
||||
SMALL_RECT region = {P(x), P(y), P(x + l - 1), P(y)};
|
||||
for (i = 0; i < l; i++) {
|
||||
ci[i].Char.UnicodeChar = 0;
|
||||
ci[i].Char.AsciiChar = *s++;
|
||||
ci[i].Attributes = (WORD) attr;
|
||||
@@ -230,58 +180,45 @@ static void putStringAttr(screen_t *this, const char *s, int attr, int x, int y)
|
||||
WriteConsoleOutputA(this->data->ho, &ci[0], size, pos00, ®ion);
|
||||
}
|
||||
|
||||
|
||||
static void putString(screen_t *this, const char *s, int x, int y)
|
||||
{
|
||||
static void putString(screen_t *this, const char *s, int x, int y) {
|
||||
this->putStringAttr(this, s, this->data->attr, x, y);
|
||||
}
|
||||
|
||||
|
||||
/* private */
|
||||
static int cci2shape(const CONSOLE_CURSOR_INFO *cci)
|
||||
{
|
||||
static int cci2shape(const CONSOLE_CURSOR_INFO *cci) {
|
||||
int shape = cci->dwSize & 255;
|
||||
if (!cci->bVisible)
|
||||
shape |= 0x2000;
|
||||
return shape;
|
||||
}
|
||||
|
||||
|
||||
static int getCursorShape(const screen_t *this)
|
||||
{
|
||||
static int getCursorShape(const screen_t *this) {
|
||||
CONSOLE_CURSOR_INFO cci;
|
||||
GetConsoleCursorInfo(this->data->ho, &cci);
|
||||
return cci2shape(&cci);
|
||||
}
|
||||
|
||||
|
||||
static void setCursorShape(screen_t *this, int shape)
|
||||
{
|
||||
static void setCursorShape(screen_t *this, int shape) {
|
||||
CONSOLE_CURSOR_INFO cci;
|
||||
cci.dwSize = shape & 255;
|
||||
cci.bVisible = (shape & 0x2000) ? 0 : 1;
|
||||
SetConsoleCursorInfo(this->data->ho, &cci);
|
||||
}
|
||||
|
||||
|
||||
static int hideCursor(screen_t *this)
|
||||
{
|
||||
static int hideCursor(screen_t *this) {
|
||||
CONSOLE_CURSOR_INFO cci;
|
||||
int shape;
|
||||
|
||||
GetConsoleCursorInfo(this->data->ho, &cci);
|
||||
shape = cci2shape(&cci);
|
||||
if (cci.bVisible)
|
||||
{
|
||||
if (cci.bVisible) {
|
||||
cci.bVisible = 0;
|
||||
SetConsoleCursorInfo(this->data->ho, &cci);
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
|
||||
|
||||
static int init(screen_t *this, int fd)
|
||||
{
|
||||
static int init(screen_t *this, int fd) {
|
||||
HANDLE hi, ho;
|
||||
CONSOLE_SCREEN_BUFFER_INFO *csbi;
|
||||
DWORD mode;
|
||||
@@ -338,7 +275,7 @@ static int init(screen_t *this, int fd)
|
||||
attr = csbi->wAttributes;
|
||||
this->data->hi = hi;
|
||||
this->data->ho = ho;
|
||||
this->data->mode = 3; // ???
|
||||
this->data->mode = 3; // ???
|
||||
this->data->attr = attr;
|
||||
this->data->init_attr = attr;
|
||||
this->data->empty_cell.Char.UnicodeChar = 0;
|
||||
@@ -350,11 +287,8 @@ static int init(screen_t *this, int fd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void updateLineN(screen_t *this, const void *line, int y, int len)
|
||||
{
|
||||
if (y >= 0 && y < this->data->rows && len > 0 && len <= 2*this->data->cols)
|
||||
{
|
||||
static void updateLineN(screen_t *this, const void *line, int y, int len) {
|
||||
if (y >= 0 && y < this->data->rows && len > 0 && len <= 2 * this->data->cols) {
|
||||
#if 0
|
||||
const char *s = (const char *) line;
|
||||
int l = len / 2;
|
||||
@@ -376,160 +310,106 @@ static void updateLineN(screen_t *this, const void *line, int y, int len)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void clearLine(screen_t *this, int y)
|
||||
{
|
||||
if (y >= 0 && y < this->data->rows)
|
||||
{
|
||||
COORD size = { P(this->data->cols), 1 };
|
||||
SMALL_RECT region = { 0, P(y), P(this->data->cols-1), P(y) };
|
||||
static void clearLine(screen_t *this, int y) {
|
||||
if (y >= 0 && y < this->data->rows) {
|
||||
COORD size = {P(this->data->cols), 1};
|
||||
SMALL_RECT region = {0, P(y), P(this->data->cols - 1), P(y)};
|
||||
WriteConsoleOutputA(this->data->ho, this->data->empty_line, size, pos00, ®ion);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void clear(screen_t *this)
|
||||
{
|
||||
static void clear(screen_t *this) {
|
||||
int y;
|
||||
for (y = 0; y < this->data->rows; y++)
|
||||
this->clearLine(this, y);
|
||||
}
|
||||
|
||||
|
||||
/* private */
|
||||
static int do_scroll(screen_t *this, int lines, int way)
|
||||
{
|
||||
static int do_scroll(screen_t *this, int lines, int way) {
|
||||
if (lines <= 0 || lines > this->data->rows)
|
||||
return 0;
|
||||
if (lines == this->data->rows)
|
||||
{
|
||||
if (lines == this->data->rows) {
|
||||
this->clear(this);
|
||||
return lines;
|
||||
}
|
||||
|
||||
SMALL_RECT rect = { 0, 0, P(this->data->cols-1), P(this->data->rows-1) };
|
||||
//SMALL_RECT clip = rect;
|
||||
COORD dest = { 0, 0 };
|
||||
switch (way)
|
||||
{
|
||||
case 0:
|
||||
rect.Top = P(rect.Top + lines);
|
||||
break;
|
||||
case 1:
|
||||
rect.Bottom = P(rect.Bottom - lines);
|
||||
dest.Y = P(dest.Y + lines);
|
||||
break;
|
||||
SMALL_RECT rect = {0, 0, P(this->data->cols - 1), P(this->data->rows - 1)};
|
||||
// SMALL_RECT clip = rect;
|
||||
COORD dest = {0, 0};
|
||||
switch (way) {
|
||||
case 0:
|
||||
rect.Top = P(rect.Top + lines);
|
||||
break;
|
||||
case 1:
|
||||
rect.Bottom = P(rect.Bottom - lines);
|
||||
dest.Y = P(dest.Y + lines);
|
||||
break;
|
||||
}
|
||||
//ScrollConsoleScreenBuffer(this->data->ho, &rect, &clip, dest, &this->data->empty_cell);
|
||||
ScrollConsoleScreenBuffer(this->data->ho, &rect, NULL, dest, &this->data->empty_cell);
|
||||
// ScrollConsoleScreenBuffer(this->data->ho, &rect, &clip, dest, &this->data->empty_cell);
|
||||
ScrollConsoleScreenBuffer(this->data->ho, &rect, nullptr, dest, &this->data->empty_cell);
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
static int scrollUp(screen_t *this, int lines)
|
||||
{
|
||||
static int scrollUp(screen_t *this, int lines) {
|
||||
lines = do_scroll(this, lines, 0);
|
||||
this->data->scroll_counter += lines;
|
||||
return lines;
|
||||
}
|
||||
|
||||
static int scrollDown(screen_t *this, int lines)
|
||||
{
|
||||
static int scrollDown(screen_t *this, int lines) {
|
||||
lines = do_scroll(this, lines, 1);
|
||||
this->data->scroll_counter -= lines;
|
||||
return lines;
|
||||
}
|
||||
|
||||
static int getScrollCounter(const screen_t *this)
|
||||
{
|
||||
return this->data->scroll_counter;
|
||||
}
|
||||
static int getScrollCounter(const screen_t *this) { return this->data->scroll_counter; }
|
||||
|
||||
|
||||
static int s_kbhit(screen_t *this)
|
||||
{
|
||||
static int s_kbhit(screen_t *this) {
|
||||
UNUSED(this);
|
||||
#if defined(HAVE_CONIO_H)
|
||||
# if defined(__RSXNT__)
|
||||
#if (HAVE_CONIO_H)
|
||||
#if defined(__RSXNT__)
|
||||
return 0;
|
||||
# elif defined(__BORLANDC__) || defined(__WATCOMC__)
|
||||
#elif defined(__BORLANDC__) || defined(__WATCOMC__)
|
||||
return kbhit();
|
||||
# else
|
||||
#else
|
||||
return _kbhit();
|
||||
# endif
|
||||
#endif
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static int intro(screen_t *this, void (*show_frames)(screen_t *) )
|
||||
{
|
||||
static int intro(screen_t *this, void (*show_frames)(screen_t *)) {
|
||||
UNUSED(this);
|
||||
UNUSED(show_frames);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void atExit(void)
|
||||
{
|
||||
static void atExit(void) {
|
||||
static int done = 0;
|
||||
if (done) return;
|
||||
if (done)
|
||||
return;
|
||||
done = 1;
|
||||
if (ae.is_valid)
|
||||
{
|
||||
if (ae.is_valid) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const screen_t driver =
|
||||
{
|
||||
sobject_destroy,
|
||||
0, /* finalize, */
|
||||
atExit,
|
||||
init,
|
||||
refresh,
|
||||
getMode,
|
||||
getPage,
|
||||
getRows,
|
||||
getCols,
|
||||
isMono,
|
||||
getFg,
|
||||
getBg,
|
||||
getCursor,
|
||||
getCursorShape,
|
||||
setFg,
|
||||
setBg,
|
||||
setCursor,
|
||||
setCursorShape,
|
||||
hideCursor,
|
||||
putChar,
|
||||
putCharAttr,
|
||||
putString,
|
||||
putStringAttr,
|
||||
clear,
|
||||
clearLine,
|
||||
updateLineN,
|
||||
scrollUp,
|
||||
scrollDown,
|
||||
getScrollCounter,
|
||||
s_kbhit,
|
||||
intro,
|
||||
(struct screen_data_t *) 0
|
||||
};
|
||||
|
||||
static const screen_t driver = {sobject_destroy, nullptr, /* finalize */
|
||||
atExit, init, refresh,
|
||||
getMode, getPage, getRows,
|
||||
getCols, isMono, getFg,
|
||||
getBg, getCursor, getCursorShape,
|
||||
setFg, setBg, setCursor,
|
||||
setCursorShape, hideCursor, putChar,
|
||||
putCharAttr, putString, putStringAttr,
|
||||
clear, clearLine, updateLineN,
|
||||
scrollUp, scrollDown, getScrollCounter,
|
||||
s_kbhit, intro, (struct screen_data_t *) nullptr};
|
||||
|
||||
/* public constructor */
|
||||
screen_t *screen_win32_construct(void)
|
||||
{
|
||||
return sobject_construct(&driver,sizeof(*driver.data));
|
||||
}
|
||||
screen_t *screen_win32_construct(void) { return sobject_construct(&driver, sizeof(*driver.data)); }
|
||||
|
||||
#endif /* (USE_SCREEN_WIN32) */
|
||||
|
||||
#endif /* defined(USE_SCREEN) && (ACC_OS_WIN32 || ACC_OS_WIN64) */
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,15 +22,14 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef UPX_SCREEN_H__
|
||||
#define UPX_SCREEN_H__ 1
|
||||
|
||||
#ifndef __UPX_SCREEN_H
|
||||
#define __UPX_SCREEN_H
|
||||
|
||||
#if defined(USE_SCREEN)
|
||||
|
||||
#if (USE_SCREEN)
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
@@ -40,12 +39,11 @@ struct screen_data_t;
|
||||
struct screen_t;
|
||||
typedef struct screen_t screen_t;
|
||||
|
||||
struct screen_t
|
||||
{
|
||||
/* public: */
|
||||
struct screen_t {
|
||||
/* public: */
|
||||
void (*destroy)(screen_t *s);
|
||||
void (*finalize)(screen_t *s);
|
||||
void (*atExit)(void); /* atexit/signal handler */
|
||||
void (*atExit)(void); /* atexit/signal handler */
|
||||
|
||||
int (*init)(screen_t *s, int fd);
|
||||
|
||||
@@ -83,13 +81,12 @@ struct screen_t
|
||||
|
||||
int (*kbhit)(screen_t *s);
|
||||
|
||||
int (*intro)(screen_t *s, void (*)(screen_t*) );
|
||||
int (*intro)(screen_t *s, void (*)(screen_t *));
|
||||
|
||||
/* private: */
|
||||
/* private: */
|
||||
struct screen_data_t *data;
|
||||
};
|
||||
|
||||
|
||||
screen_t *sobject_construct(const screen_t *c, size_t data_size);
|
||||
void sobject_destroy(screen_t *);
|
||||
screen_t *sobject_get_screen(void);
|
||||
@@ -101,52 +98,8 @@ screen_t *screen_win32_construct(void);
|
||||
|
||||
void screen_show_frames(screen_t *);
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// debugging support
|
||||
**************************************************************************/
|
||||
|
||||
#if 0
|
||||
|
||||
#undef LOG
|
||||
#undef LOGI
|
||||
#undef LOGU
|
||||
#undef LOGS
|
||||
|
||||
#if defined(SCREEN_DEBUG)
|
||||
static void LOG(const char *format, ...)
|
||||
{
|
||||
static FILE *logfile = NULL;
|
||||
va_list args;
|
||||
|
||||
if (!logfile)
|
||||
logfile = fopen("screen.log", "wt");
|
||||
if (!logfile)
|
||||
return;
|
||||
|
||||
va_start(args,format);
|
||||
vfprintf(logfile,format,args);
|
||||
fflush(logfile);
|
||||
va_end(args);
|
||||
}
|
||||
# define LOGI(x) LOG(#x " %ld\n", (long)(x))
|
||||
# define LOGU(x) LOG(#x " %lu\n", (long)(x))
|
||||
# define LOGS(x) LOG(#x " %s\n", x)
|
||||
#else
|
||||
# define LOGI(x)
|
||||
# define LOGU(x)
|
||||
# define LOGS(x)
|
||||
#endif
|
||||
|
||||
#endif /* if #0 */
|
||||
|
||||
|
||||
#endif /* USE_SCREEN */
|
||||
|
||||
#endif /* already included */
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
+42
-92
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,60 +22,55 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
long Throwable::counter = 0;
|
||||
unsigned long Throwable::counter = 0;
|
||||
|
||||
Throwable::Throwable(const char *m, int e, bool w) NOTHROW
|
||||
: super(), msg(NULL), err(e), is_warning(w)
|
||||
{
|
||||
Throwable::Throwable(const char *m, int e, bool w) noexcept : super(),
|
||||
msg(nullptr),
|
||||
err(e),
|
||||
is_warning(w) {
|
||||
if (m)
|
||||
msg = strdup(m);
|
||||
#if 0
|
||||
fprintf(stderr, "construct exception: %s %ld\n", msg, counter);
|
||||
fprintf(stderr, "construct exception: %s %lu\n", msg, counter);
|
||||
counter++;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Throwable::Throwable(const Throwable &other) NOTHROW
|
||||
: super(other), msg(NULL), err(other.err), is_warning(other.is_warning)
|
||||
{
|
||||
Throwable::Throwable(const Throwable &other) noexcept : super(other),
|
||||
msg(nullptr),
|
||||
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);
|
||||
fprintf(stderr, "copy exception: %s %lu\n", msg, counter);
|
||||
counter++;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Throwable::~Throwable() NOTHROW
|
||||
{
|
||||
Throwable::~Throwable() noexcept {
|
||||
#if 0
|
||||
counter--;
|
||||
fprintf(stderr, "destruct exception: %s %ld\n", msg, counter);
|
||||
fprintf(stderr, "destruct exception: %s %lu\n", msg, counter);
|
||||
#endif
|
||||
if (msg)
|
||||
free(msg);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// compression
|
||||
**************************************************************************/
|
||||
|
||||
void throwCantPack(const char *msg)
|
||||
{
|
||||
void throwCantPack(const char *msg) {
|
||||
// UGLY, but makes things easier
|
||||
if (opt->cmd == CMD_COMPRESS)
|
||||
throw CantPackException(msg);
|
||||
@@ -85,119 +80,78 @@ void throwCantPack(const char *msg)
|
||||
throw CantUnpackException(msg);
|
||||
}
|
||||
|
||||
void throwCantPackExact()
|
||||
{
|
||||
throwCantPack("option '--exact' does not work with this file");
|
||||
}
|
||||
void throwCantPackExact() { throwCantPack("option '--exact' does not work with this file"); }
|
||||
|
||||
void throwFilterException()
|
||||
{
|
||||
throwCantPack("filter problem");
|
||||
}
|
||||
void throwFilterException() { throwCantPack("filter problem"); }
|
||||
|
||||
void throwUnknownExecutableFormat(const char *msg, bool warn)
|
||||
{
|
||||
void throwUnknownExecutableFormat(const char *msg, bool warn) {
|
||||
throw UnknownExecutableFormatException(msg, warn);
|
||||
}
|
||||
|
||||
void throwNotCompressible(const char *msg)
|
||||
{
|
||||
throw NotCompressibleException(msg);
|
||||
}
|
||||
void throwNotCompressible(const char *msg) { throw NotCompressibleException(msg); }
|
||||
|
||||
void throwAlreadyPacked(const char *msg)
|
||||
{
|
||||
throw AlreadyPackedException(msg);
|
||||
}
|
||||
void throwAlreadyPacked(const char *msg) { throw AlreadyPackedException(msg); }
|
||||
|
||||
void throwAlreadyPackedByUPX(const char *msg)
|
||||
{
|
||||
if (msg == NULL)
|
||||
void throwAlreadyPackedByUPX(const char *msg) {
|
||||
if (msg == nullptr)
|
||||
msg = "already packed by UPX";
|
||||
throwAlreadyPacked(msg);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// decompression
|
||||
**************************************************************************/
|
||||
|
||||
void throwCantUnpack(const char *msg)
|
||||
{
|
||||
void throwCantUnpack(const char *msg) {
|
||||
// UGLY, but makes things easier
|
||||
throwCantPack(msg);
|
||||
}
|
||||
|
||||
void throwNotPacked(const char *msg)
|
||||
{
|
||||
if (msg == NULL)
|
||||
void throwNotPacked(const char *msg) {
|
||||
if (msg == nullptr)
|
||||
msg = "not packed by UPX";
|
||||
throw NotPackedException(msg);
|
||||
}
|
||||
|
||||
void throwChecksumError()
|
||||
{
|
||||
throw Exception("checksum error");
|
||||
}
|
||||
|
||||
void throwCompressedDataViolation()
|
||||
{
|
||||
throw Exception("compressed data violation");
|
||||
}
|
||||
void throwChecksumError() { throw Exception("checksum error"); }
|
||||
|
||||
void throwCompressedDataViolation() { throw Exception("compressed data violation"); }
|
||||
|
||||
/*************************************************************************
|
||||
// other
|
||||
**************************************************************************/
|
||||
|
||||
void throwInternalError(const char *msg)
|
||||
{
|
||||
throw InternalError(msg);
|
||||
}
|
||||
void throwInternalError(const char *msg) { throw InternalError(msg); }
|
||||
|
||||
void throwBadLoader()
|
||||
{
|
||||
throwInternalError("bad loader");
|
||||
}
|
||||
void throwBadLoader() { throwInternalError("bad loader"); }
|
||||
|
||||
|
||||
void throwOutOfMemoryException(const char *msg)
|
||||
{
|
||||
if (msg == NULL)
|
||||
void throwOutOfMemoryException(const char *msg) {
|
||||
if (msg == nullptr)
|
||||
msg = "out of memory";
|
||||
throw OutOfMemoryException(msg);
|
||||
}
|
||||
|
||||
void throwIOException(const char *msg, int e) { throw IOException(msg, e); }
|
||||
|
||||
void throwIOException(const char *msg, int e)
|
||||
{
|
||||
throw IOException(msg, e);
|
||||
}
|
||||
|
||||
|
||||
void throwEOFException(const char *msg, int e)
|
||||
{
|
||||
if (msg == NULL && e == 0)
|
||||
void throwEOFException(const char *msg, int e) {
|
||||
if (msg == nullptr && e == 0)
|
||||
msg = "premature end of file";
|
||||
throw EOFException(msg, e);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
const char *prettyName(const char *n) NOTHROW
|
||||
{
|
||||
if (n == NULL)
|
||||
const char *prettyName(const char *n) noexcept {
|
||||
if (n == nullptr)
|
||||
return "(null)";
|
||||
while (*n)
|
||||
{
|
||||
if (*n >= '0' && *n <= '9') // Linux ABI
|
||||
while (*n) {
|
||||
if (*n >= '0' && *n <= '9') // Linux ABI
|
||||
n++;
|
||||
else if (*n == ' ')
|
||||
n++;
|
||||
else if (strncmp(n, "class ", 6) == 0) // Visual C++
|
||||
else if (strncmp(n, "class ", 6) == 0) // Visual C++
|
||||
n += 6;
|
||||
else
|
||||
break;
|
||||
@@ -205,8 +159,4 @@ const char *prettyName(const char *n) NOTHROW
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+97
-111
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,217 +22,203 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __UPX_EXCEPT_H
|
||||
#define __UPX_EXCEPT_H
|
||||
#pragma once
|
||||
#ifndef UPX_EXCEPT_H__
|
||||
#define UPX_EXCEPT_H__ 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
const char *prettyName(const char *n) NOTHROW;
|
||||
|
||||
const char *prettyName(const char *n) noexcept;
|
||||
|
||||
/*************************************************************************
|
||||
// exceptions
|
||||
**************************************************************************/
|
||||
|
||||
class Throwable : public std::exception
|
||||
{
|
||||
class Throwable : public std::exception {
|
||||
typedef std::exception super;
|
||||
|
||||
protected:
|
||||
Throwable(const char *m = 0, int e = 0, bool w = false) NOTHROW;
|
||||
Throwable(const char *m = nullptr, int e = 0, bool w = false) noexcept;
|
||||
|
||||
public:
|
||||
Throwable(const Throwable &) NOTHROW;
|
||||
virtual ~Throwable() NOTHROW;
|
||||
const char *getMsg() const NOTHROW { return msg; }
|
||||
int getErrno() const NOTHROW { return err; }
|
||||
bool isWarning() const NOTHROW { return is_warning; }
|
||||
Throwable(const Throwable &) noexcept;
|
||||
virtual ~Throwable() noexcept;
|
||||
const char *getMsg() const noexcept { return msg; }
|
||||
int getErrno() const noexcept { return err; }
|
||||
bool isWarning() const noexcept { return is_warning; }
|
||||
|
||||
private:
|
||||
char *msg;
|
||||
int err;
|
||||
char *msg = nullptr;
|
||||
int err = 0;
|
||||
|
||||
protected:
|
||||
bool is_warning; // can be set by subclasses
|
||||
bool is_warning = false; // can be set by subclasses
|
||||
|
||||
private:
|
||||
// disable assignment
|
||||
Throwable& operator= (const Throwable &);
|
||||
// disable dynamic allocation
|
||||
DISABLE_NEW_DELETE
|
||||
Throwable &operator=(const Throwable &) = delete;
|
||||
// disable dynamic allocation => force throwing by value
|
||||
ACC_CXX_DISABLE_NEW_DELETE
|
||||
|
||||
private:
|
||||
static long counter; // for debugging
|
||||
static unsigned long counter; // for debugging
|
||||
};
|
||||
|
||||
|
||||
// Exceptions can/should be caught
|
||||
class Exception : public Throwable
|
||||
{
|
||||
class Exception : public Throwable {
|
||||
typedef Throwable super;
|
||||
public:
|
||||
Exception(const char *m = 0, int e = 0, bool w = false) NOTHROW : super(m,e,w) { }
|
||||
};
|
||||
|
||||
public:
|
||||
Exception(const char *m = nullptr, int e = 0, bool w = false) noexcept : super(m, e, w) {}
|
||||
};
|
||||
|
||||
// Errors should not be caught (or re-thrown)
|
||||
class Error : public Throwable
|
||||
{
|
||||
class Error : public Throwable {
|
||||
typedef Throwable super;
|
||||
public:
|
||||
Error(const char *m = 0, int e = 0) NOTHROW : super(m,e) { }
|
||||
};
|
||||
|
||||
public:
|
||||
Error(const char *m = nullptr, int e = 0) noexcept : super(m, e) {}
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
// system exception
|
||||
**************************************************************************/
|
||||
|
||||
class OutOfMemoryException : public Exception
|
||||
{
|
||||
class OutOfMemoryException : public Exception {
|
||||
typedef Exception super;
|
||||
|
||||
public:
|
||||
OutOfMemoryException(const char *m = 0, int e = 0) NOTHROW : super(m,e) { }
|
||||
OutOfMemoryException(const char *m = nullptr, int e = 0) noexcept : super(m, e) {}
|
||||
};
|
||||
|
||||
|
||||
class IOException : public Exception
|
||||
{
|
||||
class IOException : public Exception {
|
||||
typedef Exception super;
|
||||
|
||||
public:
|
||||
IOException(const char *m = 0, int e = 0) NOTHROW : super(m,e) { }
|
||||
IOException(const char *m = nullptr, int e = 0) noexcept : super(m, e) {}
|
||||
};
|
||||
|
||||
|
||||
class EOFException : public IOException
|
||||
{
|
||||
class EOFException : public IOException {
|
||||
typedef IOException super;
|
||||
|
||||
public:
|
||||
EOFException(const char *m = 0, int e = 0) NOTHROW : super(m,e) { }
|
||||
EOFException(const char *m = nullptr, int e = 0) noexcept : super(m, e) {}
|
||||
};
|
||||
|
||||
|
||||
class FileNotFoundException : public IOException
|
||||
{
|
||||
class FileNotFoundException : public IOException {
|
||||
typedef IOException super;
|
||||
|
||||
public:
|
||||
FileNotFoundException(const char *m = 0, int e = 0) NOTHROW : super(m,e) { }
|
||||
FileNotFoundException(const char *m = nullptr, int e = 0) noexcept : super(m, e) {}
|
||||
};
|
||||
|
||||
|
||||
class FileAlreadyExistsException : public IOException
|
||||
{
|
||||
class FileAlreadyExistsException : public IOException {
|
||||
typedef IOException super;
|
||||
public:
|
||||
FileAlreadyExistsException(const char *m = 0, int e = 0) NOTHROW : super(m,e) { }
|
||||
};
|
||||
|
||||
public:
|
||||
FileAlreadyExistsException(const char *m = nullptr, int e = 0) noexcept : super(m, e) {}
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
// application execptions
|
||||
// application exceptions
|
||||
**************************************************************************/
|
||||
|
||||
class OverlayException : public Exception
|
||||
{
|
||||
class OverlayException : public Exception {
|
||||
typedef Exception super;
|
||||
|
||||
public:
|
||||
OverlayException(const char *m = 0, bool w = false) NOTHROW : super(m,0,w) { }
|
||||
OverlayException(const char *m = nullptr, bool w = false) noexcept : super(m, 0, w) {}
|
||||
};
|
||||
|
||||
class CantPackException : public Exception
|
||||
{
|
||||
class CantPackException : public Exception {
|
||||
typedef Exception super;
|
||||
|
||||
public:
|
||||
CantPackException(const char *m = 0, bool w = false) NOTHROW : super(m,0,w) { }
|
||||
CantPackException(const char *m = nullptr, bool w = false) noexcept : super(m, 0, w) {}
|
||||
};
|
||||
|
||||
class UnknownExecutableFormatException : public CantPackException
|
||||
{
|
||||
class UnknownExecutableFormatException : public CantPackException {
|
||||
typedef CantPackException super;
|
||||
|
||||
public:
|
||||
UnknownExecutableFormatException(const char *m = 0, bool w = false) NOTHROW : super(m,w) { }
|
||||
UnknownExecutableFormatException(const char *m = nullptr, bool w = false) noexcept
|
||||
: super(m, w) {}
|
||||
};
|
||||
|
||||
class AlreadyPackedException : public CantPackException
|
||||
{
|
||||
class AlreadyPackedException : public CantPackException {
|
||||
typedef CantPackException super;
|
||||
|
||||
public:
|
||||
AlreadyPackedException(const char *m = 0) NOTHROW : super(m) { is_warning = true; }
|
||||
AlreadyPackedException(const char *m = nullptr) noexcept : super(m) { is_warning = true; }
|
||||
};
|
||||
|
||||
class NotCompressibleException : public CantPackException
|
||||
{
|
||||
class NotCompressibleException : public CantPackException {
|
||||
typedef CantPackException super;
|
||||
|
||||
public:
|
||||
NotCompressibleException(const char *m = 0) NOTHROW : super(m) { }
|
||||
NotCompressibleException(const char *m = nullptr) noexcept : super(m) {}
|
||||
};
|
||||
|
||||
|
||||
class CantUnpackException : public Exception
|
||||
{
|
||||
class CantUnpackException : public Exception {
|
||||
typedef Exception super;
|
||||
|
||||
public:
|
||||
CantUnpackException(const char *m = 0, bool w = false) NOTHROW : super(m,0,w) { }
|
||||
CantUnpackException(const char *m = nullptr, bool w = false) noexcept : super(m, 0, w) {}
|
||||
};
|
||||
|
||||
class NotPackedException : public CantUnpackException
|
||||
{
|
||||
class NotPackedException : public CantUnpackException {
|
||||
typedef CantUnpackException super;
|
||||
public:
|
||||
NotPackedException(const char *m = 0) NOTHROW : super(m,true) { }
|
||||
};
|
||||
|
||||
public:
|
||||
NotPackedException(const char *m = nullptr) noexcept : super(m, true) {}
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
// errors
|
||||
**************************************************************************/
|
||||
|
||||
class InternalError : public Error
|
||||
{
|
||||
class InternalError : public Error {
|
||||
typedef Error super;
|
||||
public:
|
||||
InternalError(const char *m = 0) NOTHROW : super(m,0) { }
|
||||
};
|
||||
|
||||
public:
|
||||
InternalError(const char *m = nullptr) noexcept : super(m, 0) {}
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
// util
|
||||
**************************************************************************/
|
||||
|
||||
#undef NORET
|
||||
#if 0 && defined(__GNUC__)
|
||||
// (noreturn) is probably not the correct semantics for throwing exceptions
|
||||
#define NORET __attribute__((__noreturn__))
|
||||
#if 1 && defined(__GNUC__)
|
||||
#define NORET __acc_noinline __attribute__((__noreturn__))
|
||||
#else
|
||||
#define NORET
|
||||
#define NORET __acc_noinline
|
||||
#endif
|
||||
|
||||
void throwCantPack(const char *msg) NORET;
|
||||
void throwCantPackExact() 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 = NULL) NORET;
|
||||
void throwFilterException() NORET;
|
||||
void throwBadLoader() NORET;
|
||||
void throwChecksumError() NORET;
|
||||
void throwCompressedDataViolation() NORET;
|
||||
void throwInternalError(const char *msg) NORET;
|
||||
void throwOutOfMemoryException(const char *msg = NULL) NORET;
|
||||
void throwIOException(const char *msg = NULL, int e = 0) NORET;
|
||||
void throwEOFException(const char *msg = NULL, int e = 0) NORET;
|
||||
NORET void throwCantPack(const char *msg);
|
||||
NORET void throwCantPackExact();
|
||||
NORET void throwUnknownExecutableFormat(const char *msg = nullptr, bool warn = false);
|
||||
NORET void throwNotCompressible(const char *msg = nullptr);
|
||||
NORET void throwAlreadyPacked(const char *msg = nullptr);
|
||||
NORET void throwAlreadyPackedByUPX(const char *msg = nullptr);
|
||||
NORET void throwCantUnpack(const char *msg);
|
||||
NORET void throwNotPacked(const char *msg = nullptr);
|
||||
NORET void throwFilterException();
|
||||
NORET void throwBadLoader();
|
||||
NORET void throwChecksumError();
|
||||
NORET void throwCompressedDataViolation();
|
||||
NORET void throwInternalError(const char *msg);
|
||||
NORET void throwOutOfMemoryException(const char *msg = nullptr);
|
||||
NORET void throwIOException(const char *msg = nullptr, int e = 0);
|
||||
NORET void throwEOFException(const char *msg = nullptr, int e = 0);
|
||||
|
||||
#undef NORET
|
||||
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* already included */
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+129
-247
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,62 +22,51 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
#include "file.h"
|
||||
#include "mem.h"
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
// static functions
|
||||
**************************************************************************/
|
||||
|
||||
void File::chmod(const char *name, int mode)
|
||||
{
|
||||
#if defined(HAVE_CHMOD)
|
||||
if (::chmod(name,mode) != 0)
|
||||
throwIOException(name,errno);
|
||||
void FileBase::chmod(const char *name, int mode) {
|
||||
#if (HAVE_CHMOD)
|
||||
if (::chmod(name, mode) != 0)
|
||||
throwIOException(name, errno);
|
||||
#else
|
||||
UNUSED(name); UNUSED(mode);
|
||||
UNUSED(name);
|
||||
UNUSED(mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void File::rename(const char *old_, const char *new_)
|
||||
{
|
||||
#if defined(__DJGPP__)
|
||||
if (::_rename(old_,new_) != 0)
|
||||
void FileBase::rename(const char *old_, const char *new_) {
|
||||
#if (ACC_OS_DOS32) && defined(__DJGPP__)
|
||||
if (::_rename(old_, new_) != 0)
|
||||
#else
|
||||
if (::rename(old_,new_) != 0)
|
||||
if (::rename(old_, new_) != 0)
|
||||
#endif
|
||||
throwIOException("rename error",errno);
|
||||
throwIOException("rename error", errno);
|
||||
}
|
||||
|
||||
|
||||
void File::unlink(const char *name)
|
||||
{
|
||||
void FileBase::unlink(const char *name) {
|
||||
if (::unlink(name) != 0)
|
||||
throwIOException(name,errno);
|
||||
throwIOException(name, errno);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
FileBase::FileBase() :
|
||||
_fd(-1), _flags(0), _shflags(0), _mode(0), _name(NULL), _offset(0), _length(0)
|
||||
{
|
||||
memset(&st,0,sizeof(st));
|
||||
FileBase::FileBase()
|
||||
: _fd(-1), _flags(0), _shflags(0), _mode(0), _name(nullptr), _offset(0), _length(0) {
|
||||
memset(&st, 0, sizeof(st));
|
||||
}
|
||||
|
||||
|
||||
FileBase::~FileBase()
|
||||
{
|
||||
#if 0 && defined(__GNUC__) // debug
|
||||
FileBase::~FileBase() {
|
||||
#if 0 && defined(__GNUC__) // debug
|
||||
if (isOpen())
|
||||
fprintf(stderr,"%s: %s\n", _name, __PRETTY_FUNCTION__);
|
||||
#endif
|
||||
@@ -87,17 +76,14 @@ FileBase::~FileBase()
|
||||
closex();
|
||||
}
|
||||
|
||||
|
||||
bool FileBase::do_sopen()
|
||||
{
|
||||
bool FileBase::do_sopen() {
|
||||
if (_shflags < 0)
|
||||
_fd = ::open(_name, _flags, _mode);
|
||||
else
|
||||
{
|
||||
#if defined(__DJGPP__)
|
||||
_fd = ::open(_name,_flags | _shflags, _mode);
|
||||
else {
|
||||
#if (ACC_OS_DOS32) && defined(__DJGPP__)
|
||||
_fd = ::open(_name, _flags | _shflags, _mode);
|
||||
#elif defined(__MINT__)
|
||||
_fd = ::open(_name,_flags | (_shflags & O_SHMODE), _mode);
|
||||
_fd = ::open(_name, _flags | (_shflags & O_SHMODE), _mode);
|
||||
#elif defined(SH_DENYRW)
|
||||
_fd = ::sopen(_name, _flags, _shflags, _mode);
|
||||
#else
|
||||
@@ -112,9 +98,7 @@ bool FileBase::do_sopen()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool FileBase::close()
|
||||
{
|
||||
bool FileBase::close() {
|
||||
bool ok = true;
|
||||
if (isOpen() && _fd != STDIN_FILENO && _fd != STDOUT_FILENO && _fd != STDERR_FILENO)
|
||||
if (::close(_fd) == -1)
|
||||
@@ -122,56 +106,22 @@ bool FileBase::close()
|
||||
_fd = -1;
|
||||
_flags = 0;
|
||||
_mode = 0;
|
||||
_name = NULL;
|
||||
_name = nullptr;
|
||||
_offset = 0;
|
||||
_length = 0;
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
void FileBase::closex()
|
||||
{
|
||||
void FileBase::closex() {
|
||||
if (!close())
|
||||
throwIOException("close failed",errno);
|
||||
throwIOException("close failed", errno);
|
||||
}
|
||||
|
||||
|
||||
int FileBase::read(void *buf, int len)
|
||||
{
|
||||
if (!isOpen() || len < 0)
|
||||
throwIOException("bad read");
|
||||
errno = 0;
|
||||
long l = acc_safe_hread(_fd, buf, len);
|
||||
if (errno)
|
||||
throwIOException("read error",errno);
|
||||
return (int) l;
|
||||
}
|
||||
|
||||
|
||||
int FileBase::readx(void *buf, int len)
|
||||
{
|
||||
int l = this->read(buf, len);
|
||||
if (l != len)
|
||||
throwEOFException();
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
void FileBase::write(const void *buf, int len)
|
||||
{
|
||||
if (!isOpen() || len < 0)
|
||||
throwIOException("bad write");
|
||||
errno = 0;
|
||||
long l = acc_safe_hwrite(_fd, buf, len);
|
||||
if (l != len)
|
||||
throwIOException("write error",errno);
|
||||
}
|
||||
|
||||
|
||||
void FileBase::seek(off_t off, int whence)
|
||||
{
|
||||
// Return value of ::seek is the resulting file offset (same as ::tell())
|
||||
upx_off_t FileBase::seek(upx_off_t off, int whence) {
|
||||
if (!isOpen())
|
||||
throwIOException("bad seek 1");
|
||||
mem_size_assert(1, off >= 0 ? off : -off); // sanity check
|
||||
if (whence == SEEK_SET) {
|
||||
if (off < 0)
|
||||
throwIOException("bad seek 2");
|
||||
@@ -183,50 +133,36 @@ void FileBase::seek(off_t off, int whence)
|
||||
off += _offset + _length;
|
||||
whence = SEEK_SET;
|
||||
}
|
||||
if (::lseek(_fd,off,whence) < 0)
|
||||
throwIOException("seek error",errno);
|
||||
// SEEK_CUR falls through to here
|
||||
upx_off_t rv = ::lseek(_fd, off, whence);
|
||||
if (rv < 0)
|
||||
throwIOException("seek error", errno);
|
||||
return rv - _offset;
|
||||
}
|
||||
|
||||
|
||||
off_t FileBase::tell() const
|
||||
{
|
||||
upx_off_t FileBase::tell() const {
|
||||
if (!isOpen())
|
||||
throwIOException("bad tell");
|
||||
off_t l = ::lseek(_fd, 0, SEEK_CUR);
|
||||
upx_off_t l = ::lseek(_fd, 0, SEEK_CUR);
|
||||
if (l < 0)
|
||||
throwIOException("tell error",errno);
|
||||
throwIOException("tell error", errno);
|
||||
return l - _offset;
|
||||
}
|
||||
|
||||
|
||||
void FileBase::set_extent(off_t offset, off_t length)
|
||||
{
|
||||
void FileBase::set_extent(upx_off_t offset, upx_off_t length) {
|
||||
_offset = offset;
|
||||
_length = length;
|
||||
}
|
||||
|
||||
off_t FileBase::st_size() const
|
||||
{
|
||||
return _length;
|
||||
}
|
||||
|
||||
upx_off_t FileBase::st_size() const { return _length; }
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
InputFile::InputFile()
|
||||
{
|
||||
}
|
||||
InputFile::InputFile() {}
|
||||
|
||||
|
||||
InputFile::~InputFile()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void InputFile::sopen(const char *name, int flags, int shflags)
|
||||
{
|
||||
void InputFile::sopen(const char *name, int flags, int shflags) {
|
||||
close();
|
||||
_name = name;
|
||||
_flags = flags;
|
||||
@@ -234,8 +170,7 @@ void InputFile::sopen(const char *name, int flags, int shflags)
|
||||
_mode = 0;
|
||||
_offset = 0;
|
||||
_length = 0;
|
||||
if (!FileBase::do_sopen())
|
||||
{
|
||||
if (!super::do_sopen()) {
|
||||
if (errno == ENOENT)
|
||||
throw FileNotFoundException(_name, errno);
|
||||
else if (errno == EEXIST)
|
||||
@@ -243,75 +178,43 @@ void InputFile::sopen(const char *name, int flags, int shflags)
|
||||
else
|
||||
throwIOException(_name, errno);
|
||||
}
|
||||
_length_orig = _length;
|
||||
}
|
||||
|
||||
|
||||
int InputFile::read(void *buf, int len)
|
||||
{
|
||||
return super::read(buf, len);
|
||||
int InputFile::read(SPAN_P(void) buf, int len) {
|
||||
if (!isOpen() || len < 0)
|
||||
throwIOException("bad read");
|
||||
mem_size_assert(1, len); // sanity check
|
||||
errno = 0;
|
||||
long l = acc_safe_hread(_fd, raw_bytes(buf, len), len);
|
||||
if (errno)
|
||||
throwIOException("read error", errno);
|
||||
return (int) l;
|
||||
}
|
||||
|
||||
int InputFile::readx(void *buf, int len)
|
||||
{
|
||||
return super::readx(buf, len);
|
||||
int InputFile::readx(SPAN_P(void) buf, int len) {
|
||||
int l = this->read(buf, len);
|
||||
if (l != len)
|
||||
throwEOFException();
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
int InputFile::read(MemBuffer *buf, int len)
|
||||
{
|
||||
buf->checkState();
|
||||
assert((unsigned)len <= buf->getSize());
|
||||
return read(buf->getVoidPtr(), len);
|
||||
}
|
||||
|
||||
int InputFile::readx(MemBuffer *buf, int len)
|
||||
{
|
||||
buf->checkState();
|
||||
assert((unsigned)len <= buf->getSize());
|
||||
return read(buf->getVoidPtr(), len);
|
||||
}
|
||||
|
||||
|
||||
int InputFile::read(MemBuffer &buf, int len)
|
||||
{
|
||||
return read(&buf, len);
|
||||
}
|
||||
|
||||
int InputFile::readx(MemBuffer &buf, int len)
|
||||
{
|
||||
return readx(&buf, len);
|
||||
}
|
||||
|
||||
|
||||
void InputFile::seek(off_t off, int whence)
|
||||
{
|
||||
super::seek(off,whence);
|
||||
}
|
||||
|
||||
|
||||
off_t InputFile::tell() const
|
||||
{
|
||||
return super::tell();
|
||||
upx_off_t InputFile::seek(upx_off_t off, int whence) {
|
||||
upx_off_t pos = super::seek(off, whence);
|
||||
if (_length < pos)
|
||||
throwIOException("bad seek 4");
|
||||
return pos;
|
||||
}
|
||||
|
||||
upx_off_t InputFile::st_size_orig() const { return _length_orig; }
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
OutputFile::OutputFile() :
|
||||
bytes_written(0)
|
||||
{
|
||||
}
|
||||
OutputFile::OutputFile() : bytes_written(0) {}
|
||||
|
||||
|
||||
OutputFile::~OutputFile()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void OutputFile::sopen(const char *name, int flags, int shflags, int mode)
|
||||
{
|
||||
void OutputFile::sopen(const char *name, int flags, int shflags, int mode) {
|
||||
close();
|
||||
_name = name;
|
||||
_flags = flags;
|
||||
@@ -319,8 +222,7 @@ void OutputFile::sopen(const char *name, int flags, int shflags, int mode)
|
||||
_mode = mode;
|
||||
_offset = 0;
|
||||
_length = 0;
|
||||
if (!FileBase::do_sopen())
|
||||
{
|
||||
if (!super::do_sopen()) {
|
||||
#if 0
|
||||
// don't throw FileNotFound here -- this is confusing
|
||||
if (errno == ENOENT)
|
||||
@@ -328,15 +230,13 @@ void OutputFile::sopen(const char *name, int flags, int shflags, int mode)
|
||||
else
|
||||
#endif
|
||||
if (errno == EEXIST)
|
||||
throw FileAlreadyExistsException(_name,errno);
|
||||
throw FileAlreadyExistsException(_name, errno);
|
||||
else
|
||||
throwIOException(_name,errno);
|
||||
throwIOException(_name, errno);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool OutputFile::openStdout(int flags, bool force)
|
||||
{
|
||||
bool OutputFile::openStdout(int flags, bool force) {
|
||||
close();
|
||||
int fd = STDOUT_FILENO;
|
||||
if (!force && acc_isatty(fd))
|
||||
@@ -353,65 +253,81 @@ bool OutputFile::openStdout(int flags, bool force)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void OutputFile::write(const void *buf, int len)
|
||||
{
|
||||
super::write(buf, len);
|
||||
void OutputFile::write(SPAN_0(const void) buf, int len) {
|
||||
if (!isOpen() || len < 0)
|
||||
throwIOException("bad write");
|
||||
// allow nullptr if len == 0
|
||||
if (len == 0)
|
||||
return;
|
||||
mem_size_assert(1, len); // sanity check
|
||||
errno = 0;
|
||||
#if 0
|
||||
fprintf(stderr, "write %p %zd (%p) %d\n", buf.raw_ptr(), buf.raw_size_in_bytes(),
|
||||
buf.raw_base(), len);
|
||||
#endif
|
||||
long l = acc_safe_hwrite(_fd, raw_bytes(buf, len), len);
|
||||
if (l != len)
|
||||
throwIOException("write error", errno);
|
||||
bytes_written += len;
|
||||
}
|
||||
|
||||
off_t OutputFile::st_size() const
|
||||
{
|
||||
if (opt->to_stdout) { // might be a pipe ==> .st_size is invalid
|
||||
return bytes_written; // too big if seek()+write() instead of rewrite()
|
||||
upx_off_t OutputFile::st_size() const {
|
||||
if (opt->to_stdout) { // might be a pipe ==> .st_size is invalid
|
||||
return bytes_written; // too big if seek()+write() instead of rewrite()
|
||||
}
|
||||
struct stat my_st;
|
||||
my_st.st_size = 0;
|
||||
if (::fstat(_fd, &my_st) != 0)
|
||||
throwIOException(_name, errno);
|
||||
return my_st.st_size;
|
||||
}
|
||||
|
||||
|
||||
void OutputFile::write(const MemBuffer *buf, int len)
|
||||
{
|
||||
buf->checkState();
|
||||
assert((unsigned)len <= buf->getSize());
|
||||
write(buf->getVoidPtr(), len);
|
||||
}
|
||||
|
||||
|
||||
void OutputFile::write(const MemBuffer &buf, int len)
|
||||
{
|
||||
write(&buf, len);
|
||||
}
|
||||
|
||||
void OutputFile::rewrite(const void *buf, int len)
|
||||
{
|
||||
void OutputFile::rewrite(SPAN_P(const void) buf, int len) {
|
||||
assert(!opt->to_stdout);
|
||||
write(buf, len);
|
||||
bytes_written -= len; // restore
|
||||
bytes_written -= len; // restore
|
||||
}
|
||||
|
||||
void OutputFile::seek(off_t off, int whence)
|
||||
{
|
||||
upx_off_t OutputFile::seek(upx_off_t off, int whence) {
|
||||
mem_size_assert(1, off >= 0 ? off : -off); // sanity check
|
||||
assert(!opt->to_stdout);
|
||||
super::seek(off,whence);
|
||||
switch (whence) {
|
||||
case SEEK_SET: {
|
||||
if (bytes_written < off) {
|
||||
bytes_written = off;
|
||||
}
|
||||
_length = bytes_written; // cheap, lazy update; needed?
|
||||
} break;
|
||||
case SEEK_END: {
|
||||
_length = bytes_written; // necessary
|
||||
} break;
|
||||
}
|
||||
return super::seek(off, whence);
|
||||
}
|
||||
|
||||
void OutputFile::set_extent(off_t offset, off_t length)
|
||||
{
|
||||
// WARNING: fsync() does not exist in some Windows environments.
|
||||
// This trick works only on UNIX-like systems.
|
||||
// int OutputFile::read(void *buf, int len)
|
||||
//{
|
||||
// fsync(_fd);
|
||||
// InputFile infile;
|
||||
// infile.open(this->getName(), O_RDONLY | O_BINARY);
|
||||
// infile.seek(this->tell(), SEEK_SET);
|
||||
// return infile.read(buf, len);
|
||||
//}
|
||||
|
||||
void OutputFile::set_extent(upx_off_t offset, upx_off_t length) {
|
||||
super::set_extent(offset, length);
|
||||
bytes_written = 0;
|
||||
if (0==offset && (off_t)~0u==length) {
|
||||
if (0 == offset && (upx_off_t) ~0u == length) {
|
||||
if (::fstat(_fd, &st) != 0)
|
||||
throwIOException(_name, errno);
|
||||
_length = st.st_size - offset;
|
||||
}
|
||||
}
|
||||
|
||||
off_t OutputFile::unset_extent()
|
||||
{
|
||||
off_t l = ::lseek(_fd, 0, SEEK_END);
|
||||
upx_off_t OutputFile::unset_extent() {
|
||||
upx_off_t l = ::lseek(_fd, 0, SEEK_END);
|
||||
if (l < 0)
|
||||
throwIOException("lseek error", errno);
|
||||
_offset = 0;
|
||||
@@ -420,48 +336,14 @@ off_t OutputFile::unset_extent()
|
||||
return _length;
|
||||
}
|
||||
|
||||
void OutputFile::dump(const char *name, const void *buf, int len, int flags)
|
||||
{
|
||||
void OutputFile::dump(const char *name, SPAN_P(const void) buf, int len, int flags) {
|
||||
if (flags < 0)
|
||||
flags = O_CREAT | O_BINARY | O_TRUNC;
|
||||
flags |= O_WRONLY;
|
||||
flags = O_CREAT | O_TRUNC;
|
||||
flags |= O_WRONLY | O_BINARY;
|
||||
OutputFile f;
|
||||
f.open(name, flags, 0600);
|
||||
f.write(buf, len);
|
||||
f.write(raw_bytes(buf, len), len);
|
||||
f.closex();
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
#if 0
|
||||
|
||||
MemoryOutputFile::MemoryOutputFile() :
|
||||
b(NULL), b_size(0), b_pos(0), bytes_written(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void MemoryOutputFile::write(const void *buf, int len)
|
||||
{
|
||||
if (!isOpen() || len < 0)
|
||||
throwIOException("bad write");
|
||||
if (len == 0)
|
||||
return;
|
||||
if (b_pos + len > b_size)
|
||||
throwIOException("write error",ENOSPC);
|
||||
memcpy(b + b_pos, buf, len);
|
||||
b_pos += len;
|
||||
bytes_written += len;
|
||||
}
|
||||
|
||||
|
||||
#endif /* if 0 */
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+61
-116
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,168 +22,113 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __UPX_FILE_H
|
||||
#define __UPX_FILE_H
|
||||
|
||||
class MemBuffer;
|
||||
|
||||
#pragma once
|
||||
#ifndef UPX_FILE_H__
|
||||
#define UPX_FILE_H__ 1
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
class File
|
||||
{
|
||||
protected:
|
||||
File() { }
|
||||
virtual ~File() { }
|
||||
public:
|
||||
static void chmod(const char *name, int mode);
|
||||
static void rename(const char *old_, const char *new_);
|
||||
static void unlink(const char *name);
|
||||
};
|
||||
|
||||
|
||||
class FileBase : public File
|
||||
{
|
||||
class FileBase {
|
||||
protected:
|
||||
FileBase();
|
||||
virtual ~FileBase();
|
||||
|
||||
public:
|
||||
virtual bool close();
|
||||
virtual void closex();
|
||||
virtual bool isOpen() const { return _fd >= 0; }
|
||||
bool close();
|
||||
void closex();
|
||||
bool isOpen() const { return _fd >= 0; }
|
||||
int getFd() const { return _fd; }
|
||||
const char *getName() const { return _name; }
|
||||
virtual off_t st_size() const; // { return _length; }
|
||||
virtual void set_extent(off_t offset, off_t length);
|
||||
|
||||
virtual upx_off_t seek(upx_off_t off, int whence);
|
||||
upx_off_t tell() const;
|
||||
virtual upx_off_t st_size() const; // { return _length; }
|
||||
virtual void set_extent(upx_off_t offset, upx_off_t length);
|
||||
|
||||
public:
|
||||
// static file-related util functions
|
||||
static void chmod(const char *name, int mode);
|
||||
static void rename(const char *old_, const char *new_);
|
||||
static void unlink(const char *name);
|
||||
|
||||
protected:
|
||||
bool do_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() const;
|
||||
int _fd = -1;
|
||||
int _flags = 0;
|
||||
int _shflags = 0;
|
||||
int _mode = 0;
|
||||
const char *_name = nullptr;
|
||||
upx_off_t _offset = 0;
|
||||
upx_off_t _length = 0;
|
||||
|
||||
int _fd;
|
||||
int _flags;
|
||||
int _shflags;
|
||||
int _mode;
|
||||
const char *_name;
|
||||
off_t _offset;
|
||||
off_t _length;
|
||||
public:
|
||||
struct stat st;
|
||||
struct stat st = {};
|
||||
};
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
class InputFile : public FileBase
|
||||
{
|
||||
class InputFile final : public FileBase {
|
||||
typedef FileBase super;
|
||||
|
||||
public:
|
||||
InputFile();
|
||||
virtual ~InputFile();
|
||||
virtual ~InputFile() {}
|
||||
|
||||
virtual void sopen(const char *name, int flags, int shflags);
|
||||
virtual void open(const char *name, int flags)
|
||||
{
|
||||
sopen(name, flags, -1);
|
||||
}
|
||||
void sopen(const char *name, int flags, int shflags);
|
||||
void open(const char *name, int flags) { sopen(name, flags, -1); }
|
||||
|
||||
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);
|
||||
int read(SPAN_P(void) buf, int len);
|
||||
int readx(SPAN_P(void) buf, int len);
|
||||
|
||||
virtual void seek(off_t off, int whence);
|
||||
virtual off_t tell() const;
|
||||
virtual upx_off_t seek(upx_off_t off, int whence) override;
|
||||
upx_off_t st_size_orig() const;
|
||||
|
||||
protected:
|
||||
upx_off_t _length_orig = 0;
|
||||
};
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
class OutputFile : public FileBase
|
||||
{
|
||||
class OutputFile final : public FileBase {
|
||||
typedef FileBase super;
|
||||
|
||||
public:
|
||||
OutputFile();
|
||||
virtual ~OutputFile();
|
||||
virtual ~OutputFile() {}
|
||||
|
||||
virtual void sopen(const char *name, int flags, int shflags, int mode);
|
||||
virtual void open(const char *name, int flags, int mode)
|
||||
{
|
||||
sopen(name, flags, -1, mode);
|
||||
}
|
||||
virtual bool openStdout(int flags=0, bool force=false);
|
||||
void sopen(const char *name, int flags, int shflags, int mode);
|
||||
void open(const char *name, int flags, int mode) { sopen(name, flags, -1, mode); }
|
||||
bool openStdout(int flags = 0, bool force = false);
|
||||
|
||||
virtual void write(const void *buf, int len);
|
||||
virtual void write(const MemBuffer *buf, int len);
|
||||
virtual void write(const MemBuffer &buf, int len);
|
||||
virtual void set_extent(off_t offset, off_t length);
|
||||
virtual off_t unset_extent(); // returns actual length
|
||||
// info: allow nullptr if len == 0
|
||||
void write(SPAN_0(const void) buf, int len);
|
||||
|
||||
off_t getBytesWritten() const { return bytes_written; }
|
||||
virtual off_t st_size() const; // { return _length; }
|
||||
virtual upx_off_t seek(upx_off_t off, int whence) override;
|
||||
virtual upx_off_t st_size() const override; // { return _length; }
|
||||
virtual void set_extent(upx_off_t offset, upx_off_t length) override;
|
||||
upx_off_t unset_extent(); // returns actual length
|
||||
|
||||
upx_off_t getBytesWritten() const { return bytes_written; }
|
||||
|
||||
// FIXME - these won't work when using the '--stdout' option
|
||||
virtual void seek(off_t off, int whence);
|
||||
virtual void rewrite(const void *buf, int len);
|
||||
void rewrite(SPAN_P(const void) buf, int len);
|
||||
|
||||
// util
|
||||
static void dump(const char *name, const void *buf, int len, int flags=-1);
|
||||
static void dump(const char *name, SPAN_P(const void) buf, int len, int flags = -1);
|
||||
|
||||
protected:
|
||||
off_t bytes_written;
|
||||
upx_off_t bytes_written = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
#if 0 /* NOT USED */
|
||||
class MemoryOutputFile : public FileBase
|
||||
{
|
||||
typedef FileBase super;
|
||||
public:
|
||||
MemoryOutputFile();
|
||||
virtual ~MemoryOutputFile() { b = NULL; }
|
||||
|
||||
virtual bool close() { b = NULL; return true; }
|
||||
virtual bool isOpen() const { return b != NULL; }
|
||||
virtual void open(void *buf, unsigned size)
|
||||
{ b = (upx_bytep) buf; b_size = size; }
|
||||
|
||||
virtual void write(const void *buf, int len);
|
||||
|
||||
off_t getBytesWritten() const { return bytes_written; }
|
||||
|
||||
protected:
|
||||
upx_bytep b;
|
||||
unsigned b_size;
|
||||
unsigned b_pos;
|
||||
off_t bytes_written;
|
||||
};
|
||||
#endif /* if 0 */
|
||||
|
||||
|
||||
#endif /* already included */
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+40
-66
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,45 +22,37 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
#include "filter.h"
|
||||
#include "file.h"
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// util
|
||||
**************************************************************************/
|
||||
|
||||
static //inline
|
||||
void initFilter(Filter *f, upx_byte *buf, unsigned buf_len)
|
||||
{
|
||||
static 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->firstcall = f->lastcall = 0;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// get a FilterEntry
|
||||
**************************************************************************/
|
||||
|
||||
const FilterImp::FilterEntry *FilterImp::getFilter(int id)
|
||||
{
|
||||
const FilterImpl::FilterEntry *FilterImpl::getFilter(int id) {
|
||||
static bool done = false;
|
||||
static unsigned char filter_map[256];
|
||||
|
||||
if (!done)
|
||||
{
|
||||
if (!done) {
|
||||
// init the filter_map[]
|
||||
assert(n_filters <= 254); // as 0xff means "empty slot"
|
||||
assert(n_filters <= 254); // as 0xff means "empty slot"
|
||||
memset(filter_map, 0xff, sizeof(filter_map));
|
||||
for (int i = 0; i < n_filters; i++)
|
||||
{
|
||||
for (int i = 0; i < n_filters; i++) {
|
||||
int filter_id = filters[i].id;
|
||||
assert(filter_id >= 0 && filter_id <= 255);
|
||||
assert(filter_map[filter_id] == 0xff);
|
||||
@@ -70,28 +62,25 @@ const FilterImp::FilterEntry *FilterImp::getFilter(int id)
|
||||
}
|
||||
|
||||
if (id < 0 || id > 255)
|
||||
return NULL;
|
||||
return nullptr;
|
||||
unsigned index = filter_map[id];
|
||||
if (index == 0xff) // empty slot
|
||||
return NULL;
|
||||
if (index == 0xff) // empty slot
|
||||
return nullptr;
|
||||
assert(filters[index].id == id);
|
||||
return &filters[index];
|
||||
}
|
||||
|
||||
|
||||
bool Filter::isValidFilter(int filter_id)
|
||||
{
|
||||
const FilterImp::FilterEntry * const fe = FilterImp::getFilter(filter_id);
|
||||
return fe != NULL;
|
||||
bool Filter::isValidFilter(int filter_id) {
|
||||
const FilterImpl::FilterEntry *const fe = FilterImpl::getFilter(filter_id);
|
||||
return fe != nullptr;
|
||||
}
|
||||
|
||||
bool Filter::isValidFilter(int filter_id, const int *allowed_filters)
|
||||
{
|
||||
bool Filter::isValidFilter(int filter_id, const int *allowed_filters) {
|
||||
if (!isValidFilter(filter_id))
|
||||
return false;
|
||||
if (filter_id == 0)
|
||||
return true;
|
||||
if (allowed_filters == NULL)
|
||||
if (allowed_filters == nullptr)
|
||||
return false;
|
||||
while (*allowed_filters != FT_END)
|
||||
if (*allowed_filters++ == filter_id)
|
||||
@@ -99,30 +88,26 @@ bool Filter::isValidFilter(int filter_id, const int *allowed_filters)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// high level API
|
||||
**************************************************************************/
|
||||
|
||||
void Filter::init(int id_, unsigned addvalue_)
|
||||
{
|
||||
void Filter::init(int id_, unsigned addvalue_) {
|
||||
this->id = id_;
|
||||
initFilter(this, NULL, 0);
|
||||
initFilter(this, nullptr, 0);
|
||||
// clear input parameters
|
||||
this->addvalue = addvalue_;
|
||||
this->preferred_ctos = NULL;
|
||||
this->preferred_ctos = nullptr;
|
||||
// clear input/output parameters
|
||||
this->cto = 0;
|
||||
this->n_mru = 0;
|
||||
}
|
||||
|
||||
|
||||
bool Filter::filter(upx_byte *buf_, unsigned buf_len_)
|
||||
{
|
||||
bool Filter::filter(upx_byte *buf_, unsigned buf_len_) {
|
||||
initFilter(this, buf_, buf_len_);
|
||||
|
||||
const FilterImp::FilterEntry * const fe = FilterImp::getFilter(id);
|
||||
if (fe == NULL)
|
||||
const FilterImpl::FilterEntry *const fe = FilterImpl::getFilter(id);
|
||||
if (fe == nullptr)
|
||||
throwInternalError("filter-1");
|
||||
if (fe->id == 0)
|
||||
return true;
|
||||
@@ -138,10 +123,10 @@ bool Filter::filter(upx_byte *buf_, unsigned buf_len_)
|
||||
if (clevel != 1)
|
||||
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);
|
||||
NO_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);
|
||||
NO_printf("filter: %02x %d\n", fe->id, r);
|
||||
if (r > 0)
|
||||
throwFilterException();
|
||||
if (r == 0)
|
||||
@@ -149,13 +134,11 @@ bool Filter::filter(upx_byte *buf_, unsigned buf_len_)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void 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_);
|
||||
|
||||
const FilterImp::FilterEntry * const fe = FilterImp::getFilter(id);
|
||||
if (fe == NULL)
|
||||
const FilterImpl::FilterEntry *const fe = FilterImpl::getFilter(id);
|
||||
if (fe == nullptr)
|
||||
throwInternalError("unfilter-1");
|
||||
if (fe->id == 0)
|
||||
return;
|
||||
@@ -166,24 +149,21 @@ void Filter::unfilter(upx_byte *buf_, unsigned buf_len_, bool verify_checksum)
|
||||
if (!fe->do_unfilter)
|
||||
throwInternalError("unfilter-2");
|
||||
|
||||
//printf("unfilter: %02x %p %d\n", this->id, this->buf, this->buf_len);
|
||||
NO_printf("unfilter: %02x %p %d\n", this->id, this->buf, this->buf_len);
|
||||
int r = (*fe->do_unfilter)(this);
|
||||
//printf("unfilter: %02x %d\n", fe->id, r);
|
||||
NO_printf("unfilter: %02x %d\n", fe->id, r);
|
||||
if (r != 0)
|
||||
throwInternalError("unfilter-3");
|
||||
//OutputFile::dump("unfilter.dat", buf, buf_len);
|
||||
// OutputFile::dump("unfilter.dat", buf, buf_len);
|
||||
|
||||
// verify checksum
|
||||
if (verify_checksum && clevel != 1)
|
||||
{
|
||||
if (verify_checksum && clevel != 1) {
|
||||
if (this->adler != upx_adler32(this->buf, this->buf_len))
|
||||
throwInternalError("unfilter-4");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Filter::verifyUnfilter()
|
||||
{
|
||||
void Filter::verifyUnfilter() {
|
||||
// Note:
|
||||
// This verify is just because of complete paranoia that there
|
||||
// could be a hidden bug in the filter implementation, and
|
||||
@@ -193,21 +173,19 @@ void Filter::verifyUnfilter()
|
||||
// See also:
|
||||
// Packer::verifyOverlappingDecompression()
|
||||
|
||||
//printf("verifyUnfilter: %02x %p %d\n", this->id, this->buf, this->buf_len);
|
||||
NO_printf("verifyUnfilter: %02x %p %d\n", this->id, this->buf, this->buf_len);
|
||||
if (clevel != 1)
|
||||
unfilter(this->buf, this->buf_len, true);
|
||||
}
|
||||
|
||||
|
||||
bool Filter::scan(const upx_byte *buf_, unsigned buf_len_)
|
||||
{
|
||||
bool Filter::scan(const upx_byte *buf_, unsigned buf_len_) {
|
||||
// Note: must use const_cast here. This is fine as the scan
|
||||
// implementations (fe->do_scan) actually don't change the buffer.
|
||||
upx_byte *b = const_cast<upx_byte *>(buf_);
|
||||
initFilter(this, b, buf_len_);
|
||||
|
||||
const FilterImp::FilterEntry * const fe = FilterImp::getFilter(id);
|
||||
if (fe == NULL)
|
||||
const FilterImpl::FilterEntry *const fe = FilterImpl::getFilter(id);
|
||||
if (fe == nullptr)
|
||||
throwInternalError("scan-1");
|
||||
if (fe->id == 0)
|
||||
return true;
|
||||
@@ -218,9 +196,9 @@ bool Filter::scan(const upx_byte *buf_, unsigned buf_len_)
|
||||
if (!fe->do_scan)
|
||||
throwInternalError("scan-2");
|
||||
|
||||
//printf("filter: %02x %p %d\n", this->id, this->buf, this->buf_len);
|
||||
NO_printf("filter: %02x %p %d\n", this->id, this->buf, this->buf_len);
|
||||
int r = (*fe->do_scan)(this);
|
||||
//printf("filter: %02x %d\n", fe->id, r);
|
||||
NO_printf("filter: %02x %d\n", fe->id, r);
|
||||
if (r > 0)
|
||||
throwFilterException();
|
||||
if (r == 0)
|
||||
@@ -228,8 +206,4 @@ bool Filter::scan(const upx_byte *buf_, unsigned buf_len_)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+27
-37
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,16 +22,12 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __UPX_FILTER_H
|
||||
#define __UPX_FILTER_H
|
||||
|
||||
class Filter;
|
||||
class FilterImp;
|
||||
|
||||
#pragma once
|
||||
#ifndef UPX_FILTER_H__
|
||||
#define UPX_FILTER_H__ 1
|
||||
|
||||
/*************************************************************************
|
||||
// A filter is a reversible operation that modifies a given
|
||||
@@ -50,14 +46,16 @@ class FilterImp;
|
||||
// to absolute addresses so that the buffer compresses better.
|
||||
**************************************************************************/
|
||||
|
||||
class Filter
|
||||
{
|
||||
class Filter {
|
||||
public:
|
||||
Filter(int level) { clevel = level; init(); }
|
||||
void init(int id=0, unsigned addvalue=0);
|
||||
Filter(int level) {
|
||||
clevel = level;
|
||||
init();
|
||||
}
|
||||
void init(int id = 0, unsigned addvalue = 0);
|
||||
|
||||
bool filter(upx_byte *buf, unsigned buf_len);
|
||||
void unfilter(upx_byte *buf, unsigned buf_len, bool verify_checksum=false);
|
||||
void unfilter(upx_byte *buf, unsigned buf_len, bool verify_checksum = false);
|
||||
void verifyUnfilter();
|
||||
bool scan(const upx_byte *buf, unsigned buf_len);
|
||||
|
||||
@@ -67,8 +65,8 @@ public:
|
||||
public:
|
||||
// Will be set by each call to filter()/unfilter().
|
||||
// Read-only afterwards.
|
||||
upx_byte *buf;
|
||||
unsigned buf_len;
|
||||
upx_byte *buf = nullptr;
|
||||
unsigned buf_len = 0;
|
||||
|
||||
// Checksum of the buffer before applying the filter
|
||||
// or after un-applying the filter.
|
||||
@@ -76,10 +74,10 @@ public:
|
||||
|
||||
// Input parameters used by various filters.
|
||||
unsigned addvalue;
|
||||
const int *preferred_ctos;
|
||||
const int *preferred_ctos = nullptr;
|
||||
|
||||
// Input/output parameters used by various filters
|
||||
unsigned char cto; // call trick offset
|
||||
unsigned char cto; // call trick offset
|
||||
|
||||
// Output used by various filters. Read only.
|
||||
unsigned calls;
|
||||
@@ -87,16 +85,15 @@ public:
|
||||
unsigned wrongcalls;
|
||||
unsigned firstcall;
|
||||
unsigned lastcall;
|
||||
unsigned n_mru; // ctojr only
|
||||
unsigned n_mru; // ctojr only
|
||||
|
||||
// Read only.
|
||||
int id;
|
||||
|
||||
private:
|
||||
int clevel; // compression level
|
||||
int clevel; // compression level
|
||||
};
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// We don't want a full OO interface here because of
|
||||
// certain implementation speed reasons.
|
||||
@@ -104,19 +101,17 @@ private:
|
||||
// This class is private to Filter - don't look.
|
||||
**************************************************************************/
|
||||
|
||||
class FilterImp
|
||||
{
|
||||
class FilterImpl {
|
||||
friend class Filter;
|
||||
|
||||
private:
|
||||
struct FilterEntry
|
||||
{
|
||||
int id; // 0 .. 255
|
||||
struct FilterEntry {
|
||||
int id; // 0 .. 255
|
||||
unsigned min_buf_len;
|
||||
unsigned max_buf_len;
|
||||
int (*do_filter)(Filter *); // filter a buffer
|
||||
int (*do_unfilter)(Filter *); // unfilter a buffer
|
||||
int (*do_scan)(Filter *); // scan a buffer
|
||||
int (*do_filter)(Filter *); // filter a buffer
|
||||
int (*do_unfilter)(Filter *); // unfilter a buffer
|
||||
int (*do_scan)(Filter *); // scan a buffer
|
||||
};
|
||||
|
||||
// get a specific filter entry
|
||||
@@ -125,14 +120,9 @@ private:
|
||||
private:
|
||||
// strictly private filter database
|
||||
static const FilterEntry filters[];
|
||||
static const int n_filters; // number of filters[]
|
||||
static const int n_filters; // number of filters[]
|
||||
};
|
||||
|
||||
|
||||
#endif /* already included */
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+44
-6
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,7 +22,7 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
@@ -459,7 +459,45 @@ static int s_ct24arm_be(Filter *f)
|
||||
#undef CT24ARM_BE
|
||||
#undef ARMCT_COND
|
||||
|
||||
/*
|
||||
vi:ts=4:et:nowrap
|
||||
*/
|
||||
/*************************************************************************
|
||||
// 26-bit ARM calltrick ("naive")
|
||||
**************************************************************************/
|
||||
|
||||
#define CT26ARM_LE(f, cond, addvalue, get, set) \
|
||||
upx_byte *b = f->buf; \
|
||||
upx_byte *b_end = b + f->buf_len - 4; \
|
||||
do { \
|
||||
if (cond) \
|
||||
{ \
|
||||
unsigned a = (unsigned) (b - f->buf); \
|
||||
f->lastcall = a; \
|
||||
set(b, get(b) + (addvalue)); \
|
||||
f->calls++; \
|
||||
} \
|
||||
b += 4; \
|
||||
} while (b < b_end); \
|
||||
if (f->lastcall) f->lastcall += 4; \
|
||||
return 0;
|
||||
|
||||
|
||||
#define ARMCT_COND (((b[3] & 0x7C) == 0x14))
|
||||
|
||||
static int f_ct26arm_le(Filter *f)
|
||||
{
|
||||
CT26ARM_LE(f, ARMCT_COND, a / 4 + f->addvalue, get_le26, set_le26)
|
||||
}
|
||||
|
||||
static int u_ct26arm_le(Filter *f)
|
||||
{
|
||||
CT26ARM_LE(f, ARMCT_COND, 0 - a / 4 - f->addvalue, get_le26, set_le26)
|
||||
}
|
||||
|
||||
static int s_ct26arm_le(Filter *f)
|
||||
{
|
||||
CT26ARM_LE(f, ARMCT_COND, a + f->addvalue, get_le26, set_dummy)
|
||||
}
|
||||
|
||||
#undef CT26ARM_LE
|
||||
#undef ARMCT_COND
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+5
-8
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,7 +22,7 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
@@ -129,6 +129,7 @@ static int F(Filter *f)
|
||||
#if 0 || defined(TESTING)
|
||||
printf("\ncalls=%d noncalls=%d noncalls2=%d text_size=%x calltrickoffset=%x\n",calls,noncalls,noncalls2,size,cto);
|
||||
#endif
|
||||
UNUSED(noncalls2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -169,8 +170,4 @@ static int U(Filter *f)
|
||||
#undef F
|
||||
#undef U
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et:nowrap
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+6
-9
@@ -2,9 +2,9 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 2000-2008 John F. Reiser
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
Copyright (C) 2000-2023 John F. Reiser
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -23,7 +23,7 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
|
||||
John F. Reiser
|
||||
<jreiser@users.sourceforge.net>
|
||||
@@ -128,6 +128,7 @@ static int F(Filter *f)
|
||||
#if 0 || defined(TESTING)
|
||||
printf("\ncalls=%d noncalls=%d noncalls2=%d text_size=%x calltrickoffset=%x\n",calls,noncalls,noncalls2,size,cto);
|
||||
#endif
|
||||
UNUSED(noncalls2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -168,8 +169,4 @@ static int U(Filter *f)
|
||||
#undef F
|
||||
#undef U
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et:nowrap
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+11
-11
@@ -2,9 +2,9 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 2000-2008 John F. Reiser
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
Copyright (C) 2000-2023 John F. Reiser
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -23,7 +23,7 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
|
||||
John F. Reiser
|
||||
<jreiser@users.sourceforge.net>
|
||||
@@ -62,7 +62,7 @@ f80_jcc2(Filter const *f)
|
||||
return f80_jmp1(f);
|
||||
}
|
||||
|
||||
static int const N_MRU = 32; // does not have to be a power of 2
|
||||
#define N_MRU 32 // does not have to be a power of 2
|
||||
|
||||
// Adaptively remember recent destinations.
|
||||
static void
|
||||
@@ -254,6 +254,7 @@ static int F(Filter *f)
|
||||
calls,noncalls,noncalls2,size,cto8);
|
||||
printf("CALL/JMP/JCC %d %d %d\n",wtally[0],wtally[1],wtally[2]);
|
||||
#endif
|
||||
UNUSED(noncalls2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -300,6 +301,9 @@ static int U(Filter *f)
|
||||
}
|
||||
else { // not 1st time at this destination
|
||||
jc >>= 1;
|
||||
if (N_MRU <= jc) {
|
||||
throwCompressedDataViolation();
|
||||
}
|
||||
int kh = jc + hand;
|
||||
if (N_MRU <= kh) {
|
||||
kh -= N_MRU;
|
||||
@@ -337,12 +341,8 @@ static int U(Filter *f)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#undef N_MRU
|
||||
#undef F
|
||||
#undef U
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et:nowrap
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+6
-9
@@ -2,9 +2,9 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 2000-2008 John F. Reiser
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
Copyright (C) 2000-2023 John F. Reiser
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -23,7 +23,7 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
|
||||
John F. Reiser
|
||||
<jreiser@users.sourceforge.net>
|
||||
@@ -129,6 +129,7 @@ static int F(Filter *f)
|
||||
#if 0 || defined(TESTING)
|
||||
printf("\ncalls=%d noncalls=%d noncalls2=%d text_size=%x calltrickoffset=%x\n",calls,noncalls,noncalls2,size,cto);
|
||||
#endif
|
||||
UNUSED(noncalls2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -171,8 +172,4 @@ static int U(Filter *f)
|
||||
#undef F
|
||||
#undef U
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et:nowrap
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+4
-8
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,7 +22,7 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
@@ -166,8 +166,4 @@ static int s_ctsw32_e9_e8(Filter *f)
|
||||
|
||||
#undef CTSW32
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et:nowrap
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/* filteri.cpp -- filter implementation (low-level)
|
||||
/* filter_impl.cpp -- filter implementation (low-level)
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,12 +22,12 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
#include "filter.h"
|
||||
#include "../conf.h"
|
||||
#include "../filter.h"
|
||||
|
||||
static unsigned
|
||||
umin(unsigned const a, unsigned const b)
|
||||
@@ -45,20 +45,20 @@ umin(unsigned const a, unsigned const b)
|
||||
// util
|
||||
**************************************************************************/
|
||||
|
||||
#include "filter/getcto.h"
|
||||
#include "getcto.h"
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
// simple filters: calltrick / swaptrick / delta / ...
|
||||
**************************************************************************/
|
||||
|
||||
#include "filter/ct.h"
|
||||
#include "filter/sw.h"
|
||||
#include "filter/ctsw.h"
|
||||
#include "ct.h"
|
||||
#include "sw.h"
|
||||
#include "ctsw.h"
|
||||
|
||||
#include "filter/sub8.h"
|
||||
#include "filter/sub16.h"
|
||||
#include "filter/sub32.h"
|
||||
#include "sub8.h"
|
||||
#include "sub16.h"
|
||||
#include "sub32.h"
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
@@ -68,25 +68,25 @@ umin(unsigned const a, unsigned const b)
|
||||
#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"
|
||||
#include "cto.h"
|
||||
#define F s_cto32_e8_bswap_le
|
||||
#include "filter/cto.h"
|
||||
#include "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"
|
||||
#include "cto.h"
|
||||
#define F s_cto32_e9_bswap_le
|
||||
#include "filter/cto.h"
|
||||
#include "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"
|
||||
#include "cto.h"
|
||||
#define F s_cto32_e8e9_bswap_le
|
||||
#include "filter/cto.h"
|
||||
#include "cto.h"
|
||||
#undef COND
|
||||
|
||||
|
||||
@@ -97,9 +97,9 @@ umin(unsigned const a, unsigned const b)
|
||||
#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"
|
||||
#include "ctoj.h"
|
||||
#define F s_ctoj32_e8e9_bswap_le
|
||||
#include "filter/ctoj.h"
|
||||
#include "ctoj.h"
|
||||
#undef COND
|
||||
|
||||
|
||||
@@ -112,9 +112,9 @@ umin(unsigned const a, unsigned const b)
|
||||
#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"
|
||||
#include "ctok.h"
|
||||
#define F s_ctok32_e8e9_bswap_le
|
||||
#include "filter/ctok.h"
|
||||
#include "ctok.h"
|
||||
#undef COND
|
||||
#undef COND2
|
||||
#undef COND1
|
||||
@@ -138,9 +138,9 @@ umin(unsigned const a, unsigned const b)
|
||||
|
||||
#define F f_ctojr32_e8e9_bswap_le
|
||||
#define U u_ctojr32_e8e9_bswap_le
|
||||
#include "filter/ctojr.h"
|
||||
#include "ctojr.h"
|
||||
#define F s_ctojr32_e8e9_bswap_le
|
||||
#include "filter/ctojr.h"
|
||||
#include "ctojr.h"
|
||||
|
||||
#undef CONDU
|
||||
#undef CONDF
|
||||
@@ -158,9 +158,9 @@ umin(unsigned const a, unsigned const b)
|
||||
#define COND(b,x) (18==(get_be32(b+x)>>26))
|
||||
#define F f_ppcbxx
|
||||
#define U u_ppcbxx
|
||||
#include "filter/ppcbxx.h"
|
||||
#include "ppcbxx.h"
|
||||
#define F s_ppcbxx
|
||||
#include "filter/ppcbxx.h"
|
||||
#include "ppcbxx.h"
|
||||
#undef COND
|
||||
|
||||
|
||||
@@ -168,9 +168,9 @@ umin(unsigned const a, unsigned const b)
|
||||
// database for use in class Filter
|
||||
**************************************************************************/
|
||||
|
||||
const FilterImp::FilterEntry FilterImp::filters[] = {
|
||||
const FilterImpl::FilterEntry FilterImpl::filters[] = {
|
||||
// no filter
|
||||
{ 0x00, 0, 0, NULL, NULL, NULL },
|
||||
{ 0x00, 0, 0, nullptr, nullptr, nullptr },
|
||||
|
||||
// 16-bit calltrick
|
||||
{ 0x01, 4, 0, f_ct16_e8, u_ct16_e8, s_ct16_e8 },
|
||||
@@ -228,6 +228,9 @@ const FilterImp::FilterEntry FilterImp::filters[] = {
|
||||
{ 0x50, 8, 0x01ffffff, f_ct24arm_le, u_ct24arm_le, s_ct24arm_le },
|
||||
{ 0x51, 8, 0x01ffffff, f_ct24arm_be, u_ct24arm_be, s_ct24arm_be },
|
||||
|
||||
// 26-bit calltrick for arm64
|
||||
{ 0x52, 8, 0x03ffffff, f_ct26arm_le, u_ct26arm_le, s_ct26arm_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 },
|
||||
@@ -258,10 +261,6 @@ const FilterImp::FilterEntry FilterImp::filters[] = {
|
||||
{ 0xd0, 8, 0, f_ppcbxx, u_ppcbxx, s_ppcbxx },
|
||||
};
|
||||
|
||||
const int FilterImp::n_filters = TABLESIZE(filters);
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et:nowrap
|
||||
*/
|
||||
const int FilterImpl::n_filters = TABLESIZE(filters);
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
+4
-9
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,7 +22,7 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
@@ -67,9 +67,4 @@ static int getcto(Filter *f, const unsigned char *buf, const int n=256)
|
||||
return ic;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et:nowrap
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+16
-15
@@ -2,9 +2,9 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 2004-2008 John F. Reiser
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
Copyright (C) 2004-2023 John F. Reiser
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -23,7 +23,7 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
|
||||
John F. Reiser
|
||||
<jreiser@users.sourceforge.net>
|
||||
@@ -47,7 +47,7 @@ static int F(Filter *f)
|
||||
// scan
|
||||
const upx_byte *b = f->buf;
|
||||
#endif
|
||||
const unsigned size = umin(f->buf_len, -(~0u<<(32 - (6+ W_CTO))));
|
||||
const unsigned size = umin(f->buf_len, 0u - (~0u<<(32 - (6+ W_CTO))));
|
||||
const unsigned size4 = size -4;
|
||||
|
||||
unsigned ic;
|
||||
@@ -72,9 +72,11 @@ static int F(Filter *f)
|
||||
}
|
||||
|
||||
if (getcto(f, buf) < 0) {
|
||||
if (0!=W_CTO) // FIXME: what is this ???
|
||||
return -1;
|
||||
#if (W_CTO != 0)
|
||||
return -1;
|
||||
#else
|
||||
f->cto = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
const unsigned char cto8 = f->cto;
|
||||
@@ -95,8 +97,9 @@ static int F(Filter *f)
|
||||
lastcall = ic;
|
||||
}
|
||||
else {
|
||||
assert(0==W_CTO // FIXME: what is this ???
|
||||
|| (~(~0u<<W_CTO) & (word>>(24+2 - W_CTO))) != cto8); // this should not happen
|
||||
#if (W_CTO != 0)
|
||||
assert((~(~0u<<W_CTO) & (word>>(24+2 - W_CTO))) != (unsigned) cto8); // this should not happen
|
||||
#endif
|
||||
lastnoncall = ic;
|
||||
noncalls++;
|
||||
}
|
||||
@@ -105,6 +108,7 @@ static int F(Filter *f)
|
||||
f->calls = calls;
|
||||
f->noncalls = noncalls;
|
||||
f->lastcall = lastcall;
|
||||
ACC_UNUSED(lastnoncall);
|
||||
|
||||
#if 0 || defined(TESTING)
|
||||
printf("\ncalls=%d noncalls=%d text_size=%x calltrickoffset=%x\n",
|
||||
@@ -122,14 +126,14 @@ static int F(Filter *f)
|
||||
static int U(Filter *f)
|
||||
{
|
||||
upx_byte *b = f->buf;
|
||||
const unsigned size4 = umin(f->buf_len - 4, -(~0u<<(32 - (6+ W_CTO))));
|
||||
const unsigned size4 = umin(f->buf_len - 4, 0u - (~0u<<(32 - (6+ W_CTO))));
|
||||
const unsigned addvalue = f->addvalue;
|
||||
|
||||
unsigned ic;
|
||||
|
||||
for (ic = 0; ic<=size4; ic+=4) if (COND(b,ic)) {
|
||||
unsigned const word = get_be32(b+ic);
|
||||
if ((~(~0u<<W_CTO) & (word>>(24+2 - W_CTO))) == f->cto) {
|
||||
if ((~(~0u<<W_CTO) & (word>>(24+2 - W_CTO))) == (unsigned) f->cto) {
|
||||
unsigned const jc = word & (~(~0u<<(26 - W_CTO)) & (~0u<<2));
|
||||
set_be32(b+ic, (0xfc000003&word)|(0x03fffffc&(jc-ic-addvalue)));
|
||||
f->calls++;
|
||||
@@ -149,7 +153,4 @@ static int U(Filter *f)
|
||||
|
||||
#undef W_CTO
|
||||
|
||||
/*
|
||||
vi:ts=4:et:nowrap
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+4
-9
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,7 +22,7 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
@@ -79,9 +79,4 @@
|
||||
assert((int)f->calls > 0); \
|
||||
return 0;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et:nowrap
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+4
-8
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,7 +22,7 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
@@ -115,8 +115,4 @@ static int s_sub16_4(Filter *f)
|
||||
#undef ADD16
|
||||
#undef SCAN16
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et:nowrap
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+4
-8
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,7 +22,7 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
@@ -115,8 +115,4 @@ static int s_sub32_4(Filter *f)
|
||||
#undef ADD32
|
||||
#undef SCAN32
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et:nowrap
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+4
-8
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,7 +22,7 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
@@ -115,8 +115,4 @@ static int s_sub8_4(Filter *f)
|
||||
#undef ADD8
|
||||
#undef SCAN8
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et:nowrap
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+4
-9
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,7 +22,7 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
@@ -180,9 +180,4 @@ static int s_sw32_e8e9(Filter *f)
|
||||
|
||||
#undef SW32
|
||||
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et:nowrap
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+88
-64
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,14 +22,14 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
#include "compress.h"
|
||||
#include "packmast.h"
|
||||
#include "packer.h"
|
||||
#include "compress/compress.h" // upx_ucl_version_string()
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
@@ -38,6 +38,13 @@
|
||||
|
||||
static bool head_done = 0;
|
||||
|
||||
// also see UPX_CONFIG_DISABLE_GITREV in CMakeLists.txt
|
||||
#if defined(UPX_VERSION_GITREV)
|
||||
const char gitrev[] = UPX_VERSION_GITREV;
|
||||
#else
|
||||
const char gitrev[1] = { 0 };
|
||||
#endif
|
||||
|
||||
void show_head(void)
|
||||
{
|
||||
FILE *f = con_term;
|
||||
@@ -47,18 +54,19 @@ 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 - 2008\n"
|
||||
"UPX %-10s Markus Oberhumer, Laszlo Molnar & John Reiser %14s\n\n",
|
||||
#if (ACC_OS_DOS16 || ACC_OS_DOS32)
|
||||
V("d"),
|
||||
#elif (ACC_OS_WIN16 || ACC_OS_WIN32 || ACC_OS_WIN64)
|
||||
V("w"),
|
||||
#elif 0 && defined(__linux__)
|
||||
V("l"),
|
||||
" Copyright (C) 1996 - " UPX_VERSION_YEAR "\n"
|
||||
#if defined(UPX_VERSION_GITREV)
|
||||
"UPX git-%6.6s%c"
|
||||
#else
|
||||
"UPX %-11s"
|
||||
#endif
|
||||
" Markus Oberhumer, Laszlo Molnar & John Reiser %14s\n\n",
|
||||
#if defined(UPX_VERSION_GITREV)
|
||||
gitrev,
|
||||
(sizeof(gitrev)-1 > 6 && gitrev[sizeof(gitrev)-2] == '+') ? '+' : ' ',
|
||||
#else
|
||||
UPX_VERSION_STRING,
|
||||
#endif
|
||||
@@ -79,7 +87,7 @@ void show_usage(void)
|
||||
FILE *f = con_term;
|
||||
|
||||
con_fprintf(f,"Usage: %s [-123456789dlthVL] [-qvfk] [-o file] %sfile..\n", progname,
|
||||
#if defined(__DJGPP__) || defined(__EMX__)
|
||||
#if (ACC_OS_DOS32) && defined(__DJGPP__)
|
||||
"[@]");
|
||||
#else
|
||||
"");
|
||||
@@ -100,7 +108,7 @@ struct PackerNames
|
||||
Entry names[64];
|
||||
size_t names_count;
|
||||
const options_t *o;
|
||||
PackerNames() : names_count(0), o(NULL) { }
|
||||
PackerNames() : names_count(0), o(nullptr) { }
|
||||
void add(const Packer *p)
|
||||
{
|
||||
p->assertPacker();
|
||||
@@ -113,7 +121,8 @@ struct PackerNames
|
||||
{
|
||||
PackerNames *self = (PackerNames *) user;
|
||||
self->add(p);
|
||||
return NULL;
|
||||
delete p; p = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
static int __acc_cdecl_qsort cmp_fname(const void *a, const void *b) {
|
||||
return strcmp(((const Entry *) a)->fname, ((const Entry *) b)->fname);
|
||||
@@ -127,16 +136,16 @@ static void show_all_packers(FILE *f, int verbose)
|
||||
{
|
||||
options_t o; o.reset();
|
||||
PackerNames pn; pn.o = &o;
|
||||
PackMaster::visitAllPackers(pn.visit, NULL, &o, &pn);
|
||||
qsort(pn.names, pn.names_count, sizeof(PackerNames::Entry), pn.cmp_fname);
|
||||
PackMaster::visitAllPackers(PackerNames::visit, nullptr, &o, &pn);
|
||||
qsort(pn.names, pn.names_count, sizeof(PackerNames::Entry), PackerNames::cmp_fname);
|
||||
size_t pos = 0;
|
||||
for (size_t i = 0; i < pn.names_count; ++i)
|
||||
{
|
||||
const char *fn = pn.names[i].fname;
|
||||
const char *sn = pn.names[i].sname;
|
||||
if (verbose)
|
||||
if (verbose > 0)
|
||||
{
|
||||
con_fprintf(f, " %-32s %s\n", fn, sn);
|
||||
con_fprintf(f, " %-36s %s\n", fn, sn);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -153,7 +162,7 @@ static void show_all_packers(FILE *f, int verbose)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!verbose && pn.names_count)
|
||||
if (verbose <= 0 && pn.names_count)
|
||||
con_fprintf(f, "\n");
|
||||
}
|
||||
|
||||
@@ -206,6 +215,7 @@ void show_help(int verbose)
|
||||
con_fprintf(f,"\nCompression tuning options:\n");
|
||||
fg = con_fg(f,fg);
|
||||
con_fprintf(f,
|
||||
" --lzma try LZMA [slower but tighter than NRV]\n"
|
||||
" --brute try all available compression methods & filters [slow]\n"
|
||||
" --ultra-brute try even more compression variants [very slow]\n"
|
||||
"\n");
|
||||
@@ -249,15 +259,6 @@ void show_help(int verbose)
|
||||
con_fprintf(f,
|
||||
" --8086 make compressed sys work on any 8086\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
|
||||
fg = con_fg(f,FG_YELLOW);
|
||||
con_fprintf(f,"Options for ps1/exe:\n");
|
||||
fg = con_fg(f,fg);
|
||||
@@ -274,7 +275,7 @@ void show_help(int verbose)
|
||||
" --le produce LE output [default: EXE]\n"
|
||||
"\n");
|
||||
fg = con_fg(f,FG_YELLOW);
|
||||
con_fprintf(f,"Options for win32/pe, rtm32/pe & arm/pe:\n");
|
||||
con_fprintf(f,"Options for win32/pe, win64/pe, rtm32/pe & arm/pe:\n");
|
||||
fg = con_fg(f,fg);
|
||||
con_fprintf(f,
|
||||
" --compress-exports=0 do not compress the export section\n"
|
||||
@@ -288,6 +289,12 @@ void show_help(int verbose)
|
||||
" --strip-relocs=0 do not strip relocations\n"
|
||||
" --strip-relocs=1 strip relocations [default]\n"
|
||||
"\n");
|
||||
fg = con_fg(f,FG_YELLOW);
|
||||
con_fprintf(f,"Options for linux/elf:\n");
|
||||
fg = con_fg(f,fg);
|
||||
con_fprintf(f,
|
||||
" --preserve-build-id copy .gnu.note.build-id to compressed output\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
con_fprintf(f, "file.. executables to (de)compress\n");
|
||||
@@ -304,17 +311,17 @@ void show_help(int verbose)
|
||||
con_fprintf(f,"\nType '%s --help' for more detailed help.\n", progname);
|
||||
}
|
||||
|
||||
con_fprintf(f,"\nUPX comes with ABSOLUTELY NO WARRANTY; for details visit http://upx.sf.net\n"
|
||||
con_fprintf(f,"\nUPX comes with ABSOLUTELY NO WARRANTY; for details visit https://upx.github.io\n"
|
||||
// "\nUPX comes with ABSOLUTELY NO WARRANTY; for details type 'upx -L'.\n"
|
||||
"");
|
||||
|
||||
#if defined(DEBUG) || defined(TESTING)
|
||||
#if DEBUG || TESTING
|
||||
fg = con_fg(f,FG_RED);
|
||||
con_fprintf(f,"\nWARNING: this version is compiled with"
|
||||
#if defined(DEBUG)
|
||||
#if DEBUG
|
||||
" -DDEBUG"
|
||||
#endif
|
||||
#if defined(TESTING)
|
||||
#if TESTING
|
||||
" -DTESTING"
|
||||
#endif
|
||||
"\n");
|
||||
@@ -342,23 +349,23 @@ void show_license(void)
|
||||
" This program is distributed in the hope that it will be useful,\n"
|
||||
" but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
||||
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
||||
" UPX License Agreement for more details.\n"
|
||||
" UPX License Agreements for more details.\n"
|
||||
"\n"
|
||||
" You should have received a copy of the UPX License Agreement\n"
|
||||
" along with this program; see the file LICENSE.\n"
|
||||
" You should have received a copy of the UPX License Agreements\n"
|
||||
" along with this program; see the files COPYING and LICENSE.\n"
|
||||
" If not, visit one of the following pages:\n"
|
||||
"\n"
|
||||
);
|
||||
int fg = con_fg(f,FG_CYAN);
|
||||
con_fprintf(f,
|
||||
" http://upx.sourceforge.net\n"
|
||||
" http://www.oberhumer.com/opensource/upx/\n"
|
||||
" https://upx.github.io\n"
|
||||
" https://www.oberhumer.com/opensource/upx/\n"
|
||||
);
|
||||
(void)con_fg(f,FG_ORANGE);
|
||||
con_fprintf(f,
|
||||
"\n"
|
||||
" Markus F.X.J. Oberhumer Laszlo Molnar\n"
|
||||
" <markus@oberhumer.com> <ml1050@users.sourceforge.net>\n"
|
||||
" <markus@oberhumer.com> <ezerotven+github@gmail.com>\n"
|
||||
);
|
||||
fg = con_fg(f,fg);
|
||||
|
||||
@@ -370,49 +377,66 @@ void show_license(void)
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
void show_version(int x)
|
||||
void show_version(bool one_line)
|
||||
{
|
||||
FILE *fp = stdout;
|
||||
const char *v;
|
||||
UNUSED(x);
|
||||
UNUSED(v);
|
||||
|
||||
#if defined(UPX_VERSION_GIT_DESCRIBE)
|
||||
fprintf(fp, "upx %s\n", UPX_VERSION_GIT_DESCRIBE);
|
||||
#elif defined(UPX_VERSION_GITREV)
|
||||
fprintf(fp, "upx %s\n", UPX_VERSION_STRING "-git-" UPX_VERSION_GITREV);
|
||||
#else
|
||||
fprintf(fp, "upx %s\n", UPX_VERSION_STRING);
|
||||
#if defined(WITH_NRV)
|
||||
#endif
|
||||
if (one_line)
|
||||
return;
|
||||
#if (WITH_NRV)
|
||||
v = upx_nrv_version_string();
|
||||
if (v != NULL && v[0])
|
||||
if (v != nullptr && v[0])
|
||||
fprintf(fp, "NRV data compression library %s\n", v);
|
||||
#endif
|
||||
#if defined(WITH_UCL)
|
||||
#if (WITH_UCL)
|
||||
v = upx_ucl_version_string();
|
||||
if (v != NULL && v[0])
|
||||
if (v != nullptr && v[0])
|
||||
fprintf(fp, "UCL data compression library %s\n", v);
|
||||
#endif
|
||||
#if defined(WITH_ZLIB)
|
||||
#if (WITH_ZLIB)
|
||||
v = upx_zlib_version_string();
|
||||
if (v != NULL && v[0])
|
||||
if (v != nullptr && v[0])
|
||||
fprintf(fp, "zlib data compression library %s\n", v);
|
||||
#endif
|
||||
#if defined(WITH_LZMA)
|
||||
#if (WITH_LZMA)
|
||||
v = upx_lzma_version_string();
|
||||
if (v != NULL && v[0])
|
||||
if (v != nullptr && v[0])
|
||||
fprintf(fp, "LZMA SDK version %s\n", v);
|
||||
#endif
|
||||
fprintf(fp, "Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer\n");
|
||||
fprintf(fp, "Copyright (C) 1996-2008 Laszlo Molnar\n");
|
||||
fprintf(fp, "Copyright (C) 2000-2008 John F. Reiser\n");
|
||||
fprintf(fp, "Copyright (C) 2002-2008 Jens Medoch\n");
|
||||
#if defined(WITH_ZLIB)
|
||||
fprintf(fp, "Copyright (C) 1995" "-2005 Jean-loup Gailly and Mark Adler\n");
|
||||
#if (WITH_ZSTD)
|
||||
v = upx_zstd_version_string();
|
||||
if (v != nullptr && v[0])
|
||||
fprintf(fp, "zstd data compression library %s\n", v);
|
||||
#endif
|
||||
#if defined(WITH_LZMA)
|
||||
#if !defined(DOCTEST_CONFIG_DISABLE)
|
||||
fprintf(fp, "doctest C++ testing framework version %s\n", DOCTEST_VERSION_STR);
|
||||
#endif
|
||||
fprintf(fp, "Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer\n");
|
||||
fprintf(fp, "Copyright (C) 1996-2023 Laszlo Molnar\n");
|
||||
fprintf(fp, "Copyright (C) 2000-2023 John F. Reiser\n");
|
||||
fprintf(fp, "Copyright (C) 2002-2023 Jens Medoch\n");
|
||||
#if (WITH_ZLIB)
|
||||
fprintf(fp, "Copyright (C) 1995" "-2022 Jean-loup Gailly and Mark Adler\n");
|
||||
#endif
|
||||
#if (WITH_LZMA)
|
||||
fprintf(fp, "Copyright (C) 1999" "-2006 Igor Pavlov\n");
|
||||
#endif
|
||||
#if (WITH_ZSTD)
|
||||
// see vendor/zstd/LICENSE; main author is Yann Collet
|
||||
fprintf(fp, "Copyright (C) 2015" "-2023 Meta Platforms, Inc. and affiliates\n");
|
||||
#endif
|
||||
#if !defined(DOCTEST_CONFIG_DISABLE)
|
||||
fprintf(fp, "Copyright (C) 2016" "-2021 Viktor Kirilov\n");
|
||||
#endif
|
||||
fprintf(fp, "UPX comes with ABSOLUTELY NO WARRANTY; for details type '%s -L'.\n", progname);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et:nowrap
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+155
-215
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,282 +22,229 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
#include "file.h"
|
||||
#include "mem.h"
|
||||
#include "util/membuffer.h"
|
||||
#include "lefile.h"
|
||||
|
||||
|
||||
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;
|
||||
ifpage_table = ofpage_table = NULL;
|
||||
ipm_entries = opm_entries = NULL;
|
||||
ires_names = ores_names = NULL;
|
||||
ifixups = ofixups = NULL;
|
||||
inonres_names = ononres_names = NULL;
|
||||
ientries = oentries = NULL;
|
||||
LeFile::LeFile(InputFile *f) : fif(f), fof(nullptr), 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);
|
||||
}
|
||||
|
||||
|
||||
LeFile::~LeFile()
|
||||
{
|
||||
delete [] iobject_table;
|
||||
delete [] oobject_table;
|
||||
delete [] ifpage_table;
|
||||
delete [] ofpage_table;
|
||||
delete [] ipm_entries;
|
||||
delete [] opm_entries;
|
||||
delete [] ires_names;
|
||||
delete [] ores_names;
|
||||
delete [] ifixups;
|
||||
delete [] ofixups;
|
||||
delete [] inonres_names;
|
||||
delete [] ononres_names;
|
||||
delete [] ientries;
|
||||
delete [] oentries;
|
||||
LeFile::~LeFile() {
|
||||
delete[] iobject_table;
|
||||
delete[] oobject_table;
|
||||
delete[] ifpage_table;
|
||||
delete[] ofpage_table;
|
||||
delete[] ipm_entries;
|
||||
delete[] opm_entries;
|
||||
delete[] ires_names;
|
||||
delete[] ores_names;
|
||||
delete[] ifixups;
|
||||
delete[] ofixups;
|
||||
delete[] inonres_names;
|
||||
delete[] ononres_names;
|
||||
delete[] ientries;
|
||||
delete[] oentries;
|
||||
}
|
||||
|
||||
|
||||
#define objects ih.object_table_entries
|
||||
#define pages ih.memory_pages
|
||||
#define mps ih.memory_page_size
|
||||
#define pages ih.memory_pages
|
||||
#define mps ih.memory_page_size
|
||||
|
||||
|
||||
void LeFile::readObjectTable()
|
||||
{
|
||||
iobject_table = new le_object_table_entry_t[soobject_table = objects];
|
||||
fif->seek(le_offset + ih.object_table_offset,SEEK_SET);
|
||||
fif->readx(iobject_table,sizeof(*iobject_table)*objects);
|
||||
void LeFile::readObjectTable() {
|
||||
soobject_table = objects;
|
||||
iobject_table = New(le_object_table_entry_t, soobject_table);
|
||||
fif->seek(le_offset + ih.object_table_offset, SEEK_SET);
|
||||
fif->readx(iobject_table, sizeof(*iobject_table) * objects);
|
||||
}
|
||||
|
||||
|
||||
void LeFile::writeObjectTable()
|
||||
{
|
||||
void LeFile::writeObjectTable() {
|
||||
if (fof && oobject_table)
|
||||
fof->write(oobject_table,sizeof(*iobject_table)*soobject_table);
|
||||
fof->write(oobject_table, sizeof(*iobject_table) * soobject_table);
|
||||
}
|
||||
|
||||
|
||||
void LeFile::readPageMap()
|
||||
{
|
||||
ipm_entries = new le_pagemap_entry_t[sopm_entries = pages];
|
||||
fif->seek(le_offset + ih.object_pagemap_offset,SEEK_SET);
|
||||
fif->readx(ipm_entries,sizeof(*ipm_entries)*pages);
|
||||
void LeFile::readPageMap() {
|
||||
sopm_entries = pages;
|
||||
ipm_entries = New(le_pagemap_entry_t, sopm_entries);
|
||||
fif->seek(le_offset + ih.object_pagemap_offset, SEEK_SET);
|
||||
fif->readx(ipm_entries, sizeof(*ipm_entries) * pages);
|
||||
|
||||
for (unsigned ic = 0; ic < pages; ic++)
|
||||
if ((ipm_entries[ic].type & 0xC0) != 0 && (ipm_entries[ic].type & 0xC0) != 0xC0)
|
||||
throwCantPack("unexpected value in page map table");
|
||||
}
|
||||
|
||||
|
||||
void LeFile::writePageMap()
|
||||
{
|
||||
void LeFile::writePageMap() {
|
||||
if (fof && opm_entries)
|
||||
fof->write(opm_entries,sizeof(*ipm_entries)*sopm_entries);
|
||||
fof->write(opm_entries, sizeof(*ipm_entries) * sopm_entries);
|
||||
}
|
||||
|
||||
|
||||
void LeFile::readResidentNames()
|
||||
{
|
||||
void LeFile::readResidentNames() {
|
||||
sores_names = ih.entry_table_offset - ih.resident_names_offset;
|
||||
ires_names = new upx_byte[sores_names];
|
||||
fif->seek(le_offset+ih.resident_names_offset,SEEK_SET);
|
||||
fif->readx(ires_names,sores_names);
|
||||
ires_names = New(upx_byte, sores_names);
|
||||
fif->seek(le_offset + ih.resident_names_offset, SEEK_SET);
|
||||
fif->readx(ires_names, sores_names);
|
||||
}
|
||||
|
||||
|
||||
void LeFile::writeResidentNames()
|
||||
{
|
||||
void LeFile::writeResidentNames() {
|
||||
if (fof && ores_names)
|
||||
fof->write(ores_names,sores_names);
|
||||
fof->write(ores_names, sores_names);
|
||||
}
|
||||
|
||||
|
||||
void LeFile::readEntryTable()
|
||||
{
|
||||
void LeFile::readEntryTable() {
|
||||
soentries = ih.fixup_page_table_offset - ih.entry_table_offset;
|
||||
fif->seek(le_offset + ih.entry_table_offset,SEEK_SET);
|
||||
ientries = new upx_byte[soentries];
|
||||
fif->readx(ientries,soentries);
|
||||
fif->seek(le_offset + ih.entry_table_offset, SEEK_SET);
|
||||
ientries = New(upx_byte, soentries);
|
||||
fif->readx(ientries, soentries);
|
||||
}
|
||||
|
||||
|
||||
void LeFile::writeEntryTable()
|
||||
{
|
||||
void LeFile::writeEntryTable() {
|
||||
if (fof && oentries)
|
||||
fof->write(oentries,soentries);
|
||||
fof->write(oentries, soentries);
|
||||
}
|
||||
|
||||
|
||||
void LeFile::readFixupPageTable()
|
||||
{
|
||||
ifpage_table = new unsigned[sofpage_table = 1+pages];
|
||||
fif->seek(le_offset + ih.fixup_page_table_offset,SEEK_SET);
|
||||
fif->readx(ifpage_table,4*sofpage_table);
|
||||
void LeFile::readFixupPageTable() {
|
||||
sofpage_table = 1 + pages;
|
||||
ifpage_table = New(unsigned, sofpage_table);
|
||||
fif->seek(le_offset + ih.fixup_page_table_offset, SEEK_SET);
|
||||
fif->readx(ifpage_table, 4 * sofpage_table);
|
||||
}
|
||||
|
||||
|
||||
void LeFile::writeFixupPageTable()
|
||||
{
|
||||
void LeFile::writeFixupPageTable() {
|
||||
if (fof && ofpage_table)
|
||||
fof->write(ofpage_table,4*sofpage_table);
|
||||
fof->write(ofpage_table, 4 * sofpage_table);
|
||||
}
|
||||
|
||||
|
||||
void LeFile::readFixups()
|
||||
{
|
||||
sofixups = get_le32(ifpage_table+pages)-get_le32(ifpage_table);
|
||||
ifixups = new upx_byte[sofixups];
|
||||
fif->seek(le_offset + ih.fixup_record_table_offset,SEEK_SET);
|
||||
fif->readx(ifixups,sofixups);
|
||||
void LeFile::readFixups() {
|
||||
sofixups = get_le32(ifpage_table + pages) - get_le32(ifpage_table);
|
||||
ifixups = New(upx_byte, sofixups);
|
||||
fif->seek(le_offset + ih.fixup_record_table_offset, SEEK_SET);
|
||||
fif->readx(ifixups, sofixups);
|
||||
}
|
||||
|
||||
|
||||
void LeFile::writeFixups()
|
||||
{
|
||||
void LeFile::writeFixups() {
|
||||
if (fof && ofixups)
|
||||
fof->write(ofixups,sofixups);
|
||||
fof->write(ofixups, sofixups);
|
||||
}
|
||||
|
||||
|
||||
unsigned LeFile::getImageSize() const
|
||||
{
|
||||
unsigned LeFile::getImageSize() const {
|
||||
unsigned n = 0;
|
||||
if (ih.memory_pages > 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;
|
||||
mb_iimage.alloc(soimage);
|
||||
mb_iimage.clear();
|
||||
iimage = mb_iimage;
|
||||
|
||||
void LeFile::readImage()
|
||||
{
|
||||
soimage = pages*mps;
|
||||
iimage.alloc(soimage);
|
||||
memset(iimage,0,soimage);
|
||||
|
||||
unsigned ic,jc;
|
||||
for (ic = jc = 0; ic < pages; ic++)
|
||||
{
|
||||
if ((ipm_entries[ic].type & 0xC0) == 0)
|
||||
{
|
||||
unsigned ic, jc;
|
||||
for (ic = jc = 0; ic < pages; ic++) {
|
||||
if ((ipm_entries[ic].type & 0xC0) == 0) {
|
||||
fif->seek(ih.data_pages_offset + exe_offset +
|
||||
(ipm_entries[ic].m*0x100 + ipm_entries[ic].l-1) * mps,SEEK_SET);
|
||||
fif->readx(iimage+jc,ic != pages-1 ? mps : ih.bytes_on_last_page);
|
||||
(ipm_entries[ic].m * 0x100 + ipm_entries[ic].l - 1) * mps,
|
||||
SEEK_SET);
|
||||
auto bytes = ic != pages - 1 ? mps : ih.bytes_on_last_page;
|
||||
fif->readx(raw_bytes(iimage + jc, bytes), bytes);
|
||||
}
|
||||
jc += mps;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LeFile::writeImage()
|
||||
{
|
||||
if (fof && oimage != NULL)
|
||||
fof->write(oimage, soimage);
|
||||
void LeFile::writeImage() {
|
||||
if (fof && oimage != nullptr)
|
||||
fof->write(raw_bytes(oimage, soimage), soimage);
|
||||
}
|
||||
|
||||
|
||||
void LeFile::readNonResidentNames()
|
||||
{
|
||||
if (ih.non_resident_name_table_length)
|
||||
{
|
||||
inonres_names = new upx_byte[sononres_names = ih.non_resident_name_table_length];
|
||||
fif->seek(exe_offset+ih.non_resident_name_table_offset,SEEK_SET);
|
||||
fif->readx(inonres_names,sononres_names);
|
||||
void LeFile::readNonResidentNames() {
|
||||
if (ih.non_resident_name_table_length) {
|
||||
sononres_names = ih.non_resident_name_table_length;
|
||||
inonres_names = New(upx_byte, sononres_names);
|
||||
fif->seek(exe_offset + ih.non_resident_name_table_offset, SEEK_SET);
|
||||
fif->readx(inonres_names, sononres_names);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LeFile::writeNonResidentNames()
|
||||
{
|
||||
void LeFile::writeNonResidentNames() {
|
||||
if (fof && ononres_names)
|
||||
fof->write(ononres_names,sononres_names);
|
||||
fof->write(ononres_names, sononres_names);
|
||||
}
|
||||
|
||||
|
||||
bool LeFile::readFileHeader()
|
||||
{
|
||||
#define H(x) get_le16(header+2*(x))
|
||||
bool LeFile::readFileHeader() {
|
||||
#define H(x) get_le16(header + 2 * (x))
|
||||
upx_byte header[0x40];
|
||||
le_offset = exe_offset = 0;
|
||||
int ic;
|
||||
|
||||
for (ic = 0; ic < 20; ic++)
|
||||
{
|
||||
fif->seek(le_offset,SEEK_SET);
|
||||
fif->readx(header,sizeof(header));
|
||||
for (ic = 0; ic < 20; ic++) {
|
||||
fif->seek(le_offset, SEEK_SET);
|
||||
fif->readx(header, sizeof(header));
|
||||
|
||||
if (memcmp(header,"MZ",2) == 0) // normal dos exe
|
||||
if (memcmp(header, "MZ", 2) == 0) // normal dos exe
|
||||
{
|
||||
exe_offset = le_offset;
|
||||
if (H(0x18/2) >= 0x40
|
||||
&& memcmp(header+0x19,"TIPPACH",7)) // new format exe
|
||||
le_offset += H(0x3c/2)+H(0x3e/2)*65536;
|
||||
else
|
||||
{
|
||||
le_offset += H(2)*512+H(1);
|
||||
if (H(0x18 / 2) >= 0x40 && memcmp(header + 0x19, "TIPPACH", 7)) // new format exe
|
||||
le_offset += H(0x3c / 2) + H(0x3e / 2) * 65536;
|
||||
else {
|
||||
le_offset += H(2) * 512 + H(1);
|
||||
if (H(1))
|
||||
le_offset -= 512;
|
||||
else if (H(2) == 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (memcmp(header,"BW",2) == 0) // used in dos4gw.exe
|
||||
le_offset += H(2)*512+H(1);
|
||||
else if (memcmp(header,"LE",2) == 0)
|
||||
} else if (memcmp(header, "BW", 2) == 0) // used in dos4gw.exe
|
||||
le_offset += H(2) * 512 + H(1);
|
||||
else if (memcmp(header, "LE", 2) == 0)
|
||||
break;
|
||||
else if (memcmp(header,"PMW1",4) == 0)
|
||||
else if (memcmp(header, "PMW1", 4) == 0)
|
||||
throwCantPack("already packed with PMWLITE");
|
||||
else
|
||||
return false;
|
||||
}
|
||||
if (ic == 20)
|
||||
return false;
|
||||
fif->seek(le_offset,SEEK_SET);
|
||||
fif->readx(&ih,sizeof(ih));
|
||||
fif->seek(le_offset, SEEK_SET);
|
||||
fif->readx(&ih, sizeof(ih));
|
||||
return true;
|
||||
#undef H
|
||||
}
|
||||
|
||||
|
||||
void LeFile::writeFile(OutputFile *f, bool le)
|
||||
{
|
||||
void LeFile::writeFile(OutputFile *f, bool le) {
|
||||
fof = f;
|
||||
memcpy (&oh,&ih,(char*)&oh.memory_pages-(char*)&oh); // copy some members of the orig. header
|
||||
memcpy(&oh, &ih,
|
||||
(char *) &oh.memory_pages - (char *) &oh); // copy some members of the orig. header
|
||||
oh.memory_page_size = mps;
|
||||
oh.object_table_offset = sizeof(oh);
|
||||
oh.object_table_entries = soobject_table;
|
||||
oh.object_pagemap_offset = oh.object_table_offset + soobject_table*sizeof(*iobject_table);
|
||||
oh.resident_names_offset = oh.object_pagemap_offset + sopm_entries*sizeof(*ipm_entries);
|
||||
oh.object_pagemap_offset = oh.object_table_offset + soobject_table * sizeof(*iobject_table);
|
||||
oh.resident_names_offset = oh.object_pagemap_offset + sopm_entries * sizeof(*ipm_entries);
|
||||
oh.entry_table_offset = oh.resident_names_offset + sores_names;
|
||||
oh.fixup_page_table_offset = oh.entry_table_offset + soentries;
|
||||
oh.fixup_record_table_offset = oh.fixup_page_table_offset + sofpage_table*4;
|
||||
oh.fixup_record_table_offset = oh.fixup_page_table_offset + sofpage_table * 4;
|
||||
oh.imported_modules_name_table_offset = oh.fixup_record_table_offset + sofixups - FIXUP_EXTRA;
|
||||
oh.imported_procedures_name_table_offset = oh.imported_modules_name_table_offset;
|
||||
oh.data_pages_offset = oh.fixup_record_table_offset + sofixups + (le ? 0 : le_offset-exe_offset);
|
||||
if (ih.non_resident_name_table_length)
|
||||
{
|
||||
oh.data_pages_offset =
|
||||
oh.fixup_record_table_offset + sofixups + (le ? 0 : le_offset - exe_offset);
|
||||
if (ih.non_resident_name_table_length) {
|
||||
oh.non_resident_name_table_offset = oh.data_pages_offset + soimage;
|
||||
oh.non_resident_name_table_length = sononres_names;
|
||||
}
|
||||
oh.fixup_size = sofixups + 4*sofpage_table;
|
||||
oh.fixup_size = sofixups + 4 * sofpage_table;
|
||||
oh.loader_size = oh.fixup_size + oh.fixup_page_table_offset - sizeof(oh);
|
||||
|
||||
fof->write(&oh,sizeof(oh));
|
||||
fof->write(&oh, sizeof(oh));
|
||||
writeObjectTable();
|
||||
writePageMap();
|
||||
writeResidentNames();
|
||||
@@ -308,60 +255,53 @@ void LeFile::writeFile(OutputFile *f, bool le)
|
||||
writeNonResidentNames();
|
||||
}
|
||||
|
||||
|
||||
void LeFile::countFixups(unsigned *counts) const
|
||||
{
|
||||
void LeFile::countFixups(unsigned *counts) const {
|
||||
const unsigned o = objects;
|
||||
memset(counts,0,sizeof(unsigned)*(o+2));
|
||||
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
|
||||
|
||||
const upx_byte *fix = ifixups;
|
||||
const unsigned sfixups = get_le32(ifpage_table+pages);
|
||||
const unsigned sfixups = get_le32(ifpage_table + pages);
|
||||
unsigned ll;
|
||||
|
||||
while ((unsigned)(fix - ifixups) < sfixups)
|
||||
{
|
||||
while (ptr_udiff_bytes(fix, ifixups) < sfixups) {
|
||||
if ((fix[1] & ~0x10) != 0)
|
||||
throwCantPack("unsupported fixup record");
|
||||
switch (*fix)
|
||||
{
|
||||
case 2: // selector fixup
|
||||
counts[o] += 9;
|
||||
fix += 5;
|
||||
break;
|
||||
case 0x12: // alias selector
|
||||
throwCantPack("16-bit selector alias fixup not yet supported");
|
||||
case 5: // 16-bit offset
|
||||
fix += (fix[1] & 0x10) ? 9 : 7;
|
||||
break;
|
||||
case 6: // 16:32 pointer
|
||||
counts[o] += 9;
|
||||
case 7: // 32-bit offset
|
||||
counts[fix[4]-1] += 4;
|
||||
fix += (fix[1] & 0x10) ? 9 : 7;
|
||||
break;
|
||||
case 0x27: // 32-bit offset list
|
||||
ll = fix[2];
|
||||
counts[fix[3]-1] += ll*4;
|
||||
fix += (fix[1] & 0x10) ? 6 : 4;
|
||||
fix += ll*2;
|
||||
break;
|
||||
case 8: // 32-bit self relative fixup
|
||||
counts[o+1] += 4;
|
||||
fix += (fix[1] & 0x10) ? 9 : 7;
|
||||
break;
|
||||
default:
|
||||
throwCantPack("unsupported fixup record");
|
||||
switch (*fix) {
|
||||
case 2: // selector fixup
|
||||
counts[o] += 9;
|
||||
fix += 5;
|
||||
break;
|
||||
case 0x12: // alias selector
|
||||
throwCantPack("16-bit selector alias fixup not yet supported");
|
||||
case 5: // 16-bit offset
|
||||
fix += (fix[1] & 0x10) ? 9 : 7;
|
||||
break;
|
||||
case 6: // 16:32 pointer
|
||||
counts[o] += 9;
|
||||
// fall through
|
||||
case 7: // 32-bit offset
|
||||
counts[fix[4] - 1] += 4;
|
||||
fix += (fix[1] & 0x10) ? 9 : 7;
|
||||
break;
|
||||
case 0x27: // 32-bit offset list
|
||||
ll = fix[2];
|
||||
counts[fix[3] - 1] += ll * 4;
|
||||
fix += (fix[1] & 0x10) ? 6 : 4;
|
||||
fix += ll * 2;
|
||||
break;
|
||||
case 8: // 32-bit self relative fixup
|
||||
counts[o + 1] += 4;
|
||||
fix += (fix[1] & 0x10) ? 9 : 7;
|
||||
break;
|
||||
default:
|
||||
throwCantPack("unsupported fixup record");
|
||||
}
|
||||
}
|
||||
counts[o]++; // extra space for 'ret'
|
||||
counts[o+1] += 4; // extra space for 0xFFFFFFFF
|
||||
counts[o]++; // extra space for 'ret'
|
||||
counts[o + 1] += 4; // extra space for 0xFFFFFFFF
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
+124
-125
@@ -2,8 +2,8 @@
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2008 Laszlo Molnar
|
||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||
Copyright (C) 1996-2023 Laszlo Molnar
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
@@ -22,24 +22,22 @@
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
||||
<markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __UPX_LEFILE_H
|
||||
#define __UPX_LEFILE_H
|
||||
#pragma once
|
||||
#ifndef UPX_LEFILE_H__
|
||||
#define UPX_LEFILE_H__ 1
|
||||
|
||||
class InputFile;
|
||||
class OutputFile;
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
class LeFile
|
||||
{
|
||||
public:
|
||||
class LeFile {
|
||||
protected:
|
||||
LeFile(InputFile *);
|
||||
virtual ~LeFile();
|
||||
|
||||
@@ -49,164 +47,170 @@ public:
|
||||
protected:
|
||||
enum { FIXUP_EXTRA = 3 };
|
||||
|
||||
struct le_header_t
|
||||
{ // 0x00
|
||||
char _[2]; // signature: 'LE' || 'LX'
|
||||
char byte_order; // 0 little endian
|
||||
char word_order; // 0 little endian
|
||||
LE32 exe_format_level; // 0
|
||||
LE16 cpu_type; // 1->286..4->586
|
||||
LE16 target_os; // 1->OS2
|
||||
char _0[4]; // module_version = 0
|
||||
struct alignas(1) le_header_t {
|
||||
// 0x00
|
||||
char _[2]; // signature: 'LE' || 'LX'
|
||||
char byte_order; // 0 little endian
|
||||
char word_order; // 0 little endian
|
||||
LE32 exe_format_level; // 0
|
||||
LE16 cpu_type; // 1->286..4->586
|
||||
LE16 target_os; // 1->OS2
|
||||
char _0[4]; // module_version = 0
|
||||
// 0x10
|
||||
LE32 module_type; // 0x200->compatible with PM windowing
|
||||
LE32 memory_pages;
|
||||
LE32 init_cs_object;
|
||||
LE32 init_eip_offset;
|
||||
LE32 module_type; // 0x200->compatible with PM windowing
|
||||
LE32 memory_pages;
|
||||
LE32 init_cs_object;
|
||||
LE32 init_eip_offset;
|
||||
// 0x20
|
||||
LE32 init_ss_object;
|
||||
LE32 init_esp_offset;
|
||||
LE32 memory_page_size;
|
||||
LE32 bytes_on_last_page;
|
||||
LE32 init_ss_object;
|
||||
LE32 init_esp_offset;
|
||||
LE32 memory_page_size;
|
||||
LE32 bytes_on_last_page;
|
||||
// 0x30
|
||||
LE32 fixup_size;
|
||||
char _1[4]; // fixup_checksum = 0
|
||||
LE32 loader_size;
|
||||
char _2[4]; // loader_checksum = 0
|
||||
LE32 fixup_size;
|
||||
char _1[4]; // fixup_checksum = 0
|
||||
LE32 loader_size;
|
||||
char _2[4]; // loader_checksum = 0
|
||||
// 0x40
|
||||
LE32 object_table_offset;
|
||||
LE32 object_table_entries;
|
||||
LE32 object_pagemap_offset;
|
||||
LE32 object_iterate_data_map_offset;
|
||||
LE32 object_table_offset;
|
||||
LE32 object_table_entries;
|
||||
LE32 object_pagemap_offset;
|
||||
LE32 object_iterate_data_map_offset;
|
||||
// 0x50
|
||||
char _3[4]; // resource_offset
|
||||
LE32 resource_entries;
|
||||
LE32 resident_names_offset;
|
||||
LE32 entry_table_offset;
|
||||
char _3[4]; // resource_offset
|
||||
LE32 resource_entries;
|
||||
LE32 resident_names_offset;
|
||||
LE32 entry_table_offset;
|
||||
// 0x60
|
||||
char _4[4]; // module_directives_table_offset = 0
|
||||
LE32 module_directives_entries;
|
||||
LE32 fixup_page_table_offset;
|
||||
LE32 fixup_record_table_offset;
|
||||
char _4[4]; // module_directives_table_offset = 0
|
||||
LE32 module_directives_entries;
|
||||
LE32 fixup_page_table_offset;
|
||||
LE32 fixup_record_table_offset;
|
||||
// 0x70
|
||||
LE32 imported_modules_name_table_offset;
|
||||
LE32 imported_modules_count;
|
||||
LE32 imported_procedures_name_table_offset;
|
||||
char _5[4]; // per_page_checksum_table_offset = 0
|
||||
LE32 imported_modules_name_table_offset;
|
||||
LE32 imported_modules_count;
|
||||
LE32 imported_procedures_name_table_offset;
|
||||
char _5[4]; // per_page_checksum_table_offset = 0
|
||||
// 0x80
|
||||
LE32 data_pages_offset;
|
||||
char _6[4]; // preload_page_count = 0
|
||||
LE32 non_resident_name_table_offset;
|
||||
LE32 non_resident_name_table_length;
|
||||
LE32 data_pages_offset;
|
||||
char _6[4]; // preload_page_count = 0
|
||||
LE32 non_resident_name_table_offset;
|
||||
LE32 non_resident_name_table_length;
|
||||
// 0x90
|
||||
char _7[4]; //non_resident_names_checksum
|
||||
LE32 automatic_data_object;
|
||||
char _7[4]; // non_resident_names_checksum
|
||||
LE32 automatic_data_object;
|
||||
#if 1
|
||||
char _8[44];
|
||||
char _8[44];
|
||||
#else
|
||||
LE32 debug_info_offset;
|
||||
LE32 debug_info_length;
|
||||
LE32 debug_info_offset;
|
||||
LE32 debug_info_length;
|
||||
// 0xA0
|
||||
LE32 preload_instance_pages;
|
||||
LE32 demand_instance_pages;
|
||||
LE32 extra_heap_alloc;
|
||||
char reserved[12];
|
||||
LE32 versioninfo;
|
||||
LE32 unkown;
|
||||
LE32 preload_instance_pages;
|
||||
LE32 demand_instance_pages;
|
||||
LE32 extra_heap_alloc;
|
||||
char reserved[12];
|
||||
LE32 versioninfo;
|
||||
LE32 unknown;
|
||||
// 0xC0
|
||||
LE16 device_id;
|
||||
LE16 ddk_version;
|
||||
LE16 device_id;
|
||||
LE16 ddk_version;
|
||||
#endif
|
||||
}
|
||||
__attribute_packed;
|
||||
};
|
||||
|
||||
struct le_object_table_entry_t
|
||||
{
|
||||
LE32 virtual_size;
|
||||
LE32 base_address;
|
||||
LE32 flags;
|
||||
LE32 pagemap_index;
|
||||
LE32 npages;
|
||||
LE32 reserved;
|
||||
}
|
||||
__attribute_packed;
|
||||
struct alignas(1) le_object_table_entry_t {
|
||||
LE32 virtual_size;
|
||||
LE32 base_address;
|
||||
LE32 flags;
|
||||
LE32 pagemap_index;
|
||||
LE32 npages;
|
||||
LE32 reserved;
|
||||
};
|
||||
|
||||
struct le_pagemap_entry_t
|
||||
{
|
||||
struct alignas(1) le_pagemap_entry_t {
|
||||
unsigned char h;
|
||||
unsigned char m;
|
||||
unsigned char l;
|
||||
unsigned char type; // 0x00-legal;0x40-iterated;0x80-invalid;0xC0-zeroed
|
||||
}
|
||||
__attribute_packed;
|
||||
unsigned char type; // 0x00-legal;0x40-iterated;0x80-invalid;0xC0-zeroed
|
||||
};
|
||||
|
||||
virtual void readObjectTable();
|
||||
virtual void writeObjectTable();
|
||||
//virtual void encodeObjectTable(){oobject_table = iobject_table; iobject_table = NULL;}
|
||||
//virtual void decodeObjectTable(){encodeObjectTable();}
|
||||
// virtual void encodeObjectTable(){oobject_table = iobject_table; iobject_table = nullptr;}
|
||||
// virtual void decodeObjectTable(){encodeObjectTable();}
|
||||
|
||||
virtual void readFixupPageTable();
|
||||
virtual void writeFixupPageTable();
|
||||
//virtual void encodeFixupPageTable(){ofpage_table = ifpage_table; ifpage_table = NULL;}
|
||||
//virtual void decodeFixupPageTable(){encodeFixupPageTable();}
|
||||
// virtual void encodeFixupPageTable(){ofpage_table = ifpage_table; ifpage_table = nullptr;}
|
||||
// virtual void decodeFixupPageTable(){encodeFixupPageTable();}
|
||||
|
||||
virtual void readPageMap();
|
||||
virtual void writePageMap();
|
||||
virtual void encodePageMap(){opm_entries = ipm_entries; ipm_entries = NULL;}
|
||||
virtual void decodePageMap(){encodePageMap();}
|
||||
virtual void encodePageMap() {
|
||||
opm_entries = ipm_entries;
|
||||
ipm_entries = nullptr;
|
||||
}
|
||||
virtual void decodePageMap() { encodePageMap(); }
|
||||
|
||||
virtual void readResidentNames();
|
||||
virtual void writeResidentNames();
|
||||
virtual void encodeResidentNames(){ores_names = ires_names; ires_names = NULL;}
|
||||
virtual void decodeResidentNames(){encodeResidentNames();}
|
||||
virtual void encodeResidentNames() {
|
||||
ores_names = ires_names;
|
||||
ires_names = nullptr;
|
||||
}
|
||||
virtual void decodeResidentNames() { encodeResidentNames(); }
|
||||
|
||||
virtual void readNonResidentNames();
|
||||
virtual void writeNonResidentNames();
|
||||
virtual void encodeNonResidentNames(){ononres_names = inonres_names; inonres_names = NULL;}
|
||||
virtual void decodeNonResidentNames(){encodeNonResidentNames();}
|
||||
virtual void encodeNonResidentNames() {
|
||||
ononres_names = inonres_names;
|
||||
inonres_names = nullptr;
|
||||
}
|
||||
virtual void decodeNonResidentNames() { encodeNonResidentNames(); }
|
||||
|
||||
virtual void readEntryTable();
|
||||
virtual void writeEntryTable();
|
||||
//virtual void encodeEntryTable(){oentries = ientries; ientries = NULL;}
|
||||
//virtual void decodeEntryTable(){encodeEntryTable();}
|
||||
// virtual void encodeEntryTable(){oentries = ientries; ientries = nullptr;}
|
||||
// virtual void decodeEntryTable(){encodeEntryTable();}
|
||||
|
||||
virtual void readFixups();
|
||||
virtual void writeFixups();
|
||||
//virtual void encodeFixups(){ofixups = ifixups; ifixups = NULL;}
|
||||
//virtual void decodeFixups(){encodeFixups();}
|
||||
// virtual void encodeFixups(){ofixups = ifixups; ifixups = nullptr;}
|
||||
// virtual void decodeFixups(){encodeFixups();}
|
||||
|
||||
virtual void readImage();
|
||||
virtual void writeImage();
|
||||
//virtual void encodeImage(){oimage = iimage; iimage = NULL;}
|
||||
//virtual void decodeImage(){encodeImage();}
|
||||
// virtual void encodeImage(){oimage = iimage; iimage = nullptr;}
|
||||
// virtual void decodeImage(){encodeImage();}
|
||||
|
||||
void countFixups(unsigned *) const;
|
||||
unsigned getImageSize() const;
|
||||
|
||||
InputFile *fif;
|
||||
OutputFile *fof;
|
||||
long le_offset;
|
||||
long exe_offset;
|
||||
InputFile *fif = nullptr;
|
||||
OutputFile *fof = nullptr;
|
||||
unsigned le_offset;
|
||||
unsigned exe_offset;
|
||||
|
||||
le_header_t ih;
|
||||
le_header_t oh;
|
||||
|
||||
le_object_table_entry_t *iobject_table;
|
||||
le_object_table_entry_t *oobject_table;
|
||||
unsigned *ifpage_table;
|
||||
unsigned *ofpage_table;
|
||||
le_pagemap_entry_t *ipm_entries;
|
||||
le_pagemap_entry_t *opm_entries;
|
||||
upx_byte *ires_names;
|
||||
upx_byte *ores_names;
|
||||
upx_byte *ifixups;
|
||||
upx_byte *ofixups;
|
||||
upx_byte *inonres_names;
|
||||
upx_byte *ononres_names;
|
||||
MemBuffer iimage;
|
||||
MemBuffer oimage;
|
||||
upx_byte *ientries;
|
||||
upx_byte *oentries;
|
||||
le_object_table_entry_t *iobject_table = nullptr;
|
||||
le_object_table_entry_t *oobject_table = nullptr;
|
||||
unsigned *ifpage_table = nullptr;
|
||||
unsigned *ofpage_table = nullptr;
|
||||
le_pagemap_entry_t *ipm_entries = nullptr;
|
||||
le_pagemap_entry_t *opm_entries = nullptr;
|
||||
upx_byte *ires_names = nullptr;
|
||||
upx_byte *ores_names = nullptr;
|
||||
upx_byte *ifixups = nullptr;
|
||||
upx_byte *ofixups = nullptr;
|
||||
upx_byte *inonres_names = nullptr;
|
||||
upx_byte *ononres_names = nullptr;
|
||||
MemBuffer mb_iimage;
|
||||
SPAN_0(upx_byte) iimage = nullptr;
|
||||
MemBuffer mb_oimage;
|
||||
SPAN_0(upx_byte) oimage = nullptr;
|
||||
upx_byte *ientries = nullptr;
|
||||
upx_byte *oentries = nullptr;
|
||||
|
||||
unsigned soobject_table;
|
||||
unsigned sofpage_table;
|
||||
@@ -219,15 +223,10 @@ protected:
|
||||
|
||||
private:
|
||||
// disable copy and assignment
|
||||
LeFile(const LeFile &); // {}
|
||||
LeFile& operator= (const LeFile &); // { return *this; }
|
||||
LeFile(const LeFile &) = delete;
|
||||
LeFile &operator=(const LeFile &) = delete;
|
||||
};
|
||||
|
||||
|
||||
#endif /* already included */
|
||||
|
||||
|
||||
/*
|
||||
vi:ts=4:et
|
||||
*/
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user