Compare commits

..

245 Commits

Author SHA1 Message Date
Markus F.X.J. Oberhumer 9c46f4653f all: prepare for release 2023-10-26 11:09:48 +02:00
Markus F.X.J. Oberhumer 29b4752d0e src: add some noexcept 2023-10-26 00:28:36 +02:00
Markus F.X.J. Oberhumer 2724039c09 submodules: update for new versions 2023-10-26 00:23:57 +02:00
Markus F.X.J. Oberhumer 6ae4e88475 cmake: fix Xcode generator build 2023-10-25 06:47:09 +02:00
Markus F.X.J. Oberhumer facabd68d7 all: more minor cleanups 2023-10-24 23:56:55 +02:00
Markus F.X.J. Oberhumer 18f043015e all: minor cleanups 2023-10-24 22:54:54 +02:00
Markus F.X.J. Oberhumer ab259a1af9 src/pefile: try to clean up reloc handling 2023-10-24 11:47:23 +02:00
Markus F.X.J. Oberhumer 1dd96a7628 src/pefile: stricter reloc checks; cleanups 2023-10-23 14:26:37 +02:00
Markus F.X.J. Oberhumer 1ee7ecb1f0 all: prefer using utimensat() 2023-10-22 13:29:26 +02:00
Markus F.X.J. Oberhumer 67548a4d9a src: minor cleanups 2023-10-22 00:45:06 +02:00
Markus F.X.J. Oberhumer 9fbe95ad48 all: cleanups 2023-10-21 11:22:18 +02:00
dependabot[bot] 91c15b2475 build(deps): bump crate-ci/typos from 1.16.19 to 1.16.20
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.16.19 to 1.16.20.
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/typos/compare/35a8bc67870d6c0b7407683319ae175577e24261...c004e98018d8621614d1ca516eed8ca2d04b365a)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-18 16:00:48 +00:00
Markus F.X.J. Oberhumer c9550b48d8 all: disable packing macOS binaries for now 2023-10-18 07:04:00 +02:00
Markus F.X.J. Oberhumer a1d090a6fd src/stub: add a "clang-format off" directive 2023-10-15 10:55:15 +02:00
Markus F.X.J. Oberhumer 4870765e1b all: disable packing macOS binaries for now 2023-10-15 10:15:46 +02:00
Markus F.X.J. Oberhumer d8be2ed276 src/pefile.cpp: cleanup reloc handling and add more checks 2023-10-14 19:24:44 +02:00
Markus F.X.J. Oberhumer 2b371e99bd src/util: minor xspan enhancements 2023-10-14 05:58:47 +02:00
Markus F.X.J. Oberhumer 005e39871b CI updates 2023-10-13 00:49:01 +02:00
Markus F.X.J. Oberhumer 96dd9eeb44 CI updates 2023-10-13 00:01:00 +02:00
John Reiser 65b06f6046 More LZMA inSize (srclen) defense
https://github.com/upx/upx/issues/717

	modified:   stub/src/amd64-darwin.dylib-entry.S  fixed
	modified:   stub/src/amd64-darwin.macho-entry.S  fixed
	modified:   stub/src/amd64-linux.elf-so_entry.S  comment-only
	modified:   stub/src/i386-linux.elf-so_entry.S  comment-only

	modified:   stub/amd64-darwin.dylib-entry.h
	modified:   stub/amd64-darwin.macho-entry.h
	modified:   stub/amd64-linux.elf-so_entry.h
	modified:   stub/tmp/amd64-darwin.dylib-entry.bin.dump
	modified:   stub/tmp/amd64-darwin.macho-entry.bin.dump
	modified:   stub/tmp/amd64-linux.elf-so_entry.bin.dump

Find+fix steps that were performed:
1. Find all 'add' instructions that compute "eof".
NRV run-time decompressors ignore srclen, so 'add' can be ignored for them.

$ cd upx-devel4/src/stub
$ grep -sr 'add.*eof' src  |  grep -v 'nrv2._d.*.S'  |  sort
src/amd64-darwin.dylib-entry.S:        addq src,lsrc; push lsrc  // &input_eof
src/amd64-darwin.macho-entry.S:        addq src,lsrc; push lsrc  // &input_eof
src/amd64-linux.elf-entry.S:        addq src,lsrc; push lsrc  // &input_eof
src/amd64-linux.elf-so_entry.S:        addq src,lsrc; push lsrc  // MATCH_05  &input_eof
src/amd64-linux.elf-so_main.c:            void *mfd_addr = Pmap(0, sizeof(code), PROT_READ|PROT_EXEC, MAP_PRIVATE, mfd, 0);
src/amd64-linux.shlib-init.S:        addq src,lsrc; push lsrc  // &input_eof
src/arch/amd64/lzma_d.S://      addq src,lsrc; push lsrc  // &input_eof
src/i386-expand.S:    add src,%ecx; push %ecx  // MATCH_52  eof_src
src/i386-linux.elf-so_entry.S:        add src,lsrc; push lsrc  // MATCH_05  &input_eof

2.  Case-by-case inspection

src/amd64-darwin.dylib-entry.S:        addq src,lsrc; push lsrc  // &input_eof
    restoring 'subq' is added in this commit

src/amd64-darwin.macho-entry.S:        addq src,lsrc; push lsrc  // &input_eof
    restoring 'subq' is added in this commit

src/amd64-linux.elf-entry.S:        addq src,lsrc; push lsrc  // &input_eof
    a restoring 'subq' is already next

src/amd64-linux.elf-so_entry.S:        addq src,lsrc; push lsrc  // MATCH_05  &input_eof
    lsrc is dead for inlined nrv2b

src/amd64-linux.elf-so_main.c:            void *mfd_addr = Pmap(0, sizeof(code), PROT_READ|PROT_EXEC, MAP_PRIVATE, mfd, 0);
    .c code

src/amd64-linux.shlib-init.S:        addq src,lsrc; push lsrc  // &input_eof
    restoring 'subq' is already next

src/arch/amd64/lzma_d.S://      addq src,lsrc; push lsrc  // &input_eof
    comment that explains preceding actions in ELFMAINX; a restoring 'subq' is already next

src/i386-expand.S:    add src,%ecx; push %ecx  // MATCH_52  eof_src
    %ecx is dead

src/i386-linux.elf-so_entry.S:        add src,lsrc; push lsrc  // MATCH_05  &input_eof
    lsrc is dead for inlined nrv2b
2023-10-12 10:41:13 -07:00
John Reiser 0515be4334 LZMA on AMD64 had bug in calling sequence, leading to random exit(127)
LzmaDecode randomly decided that the input had ended in the middle,
because of error in interface between ELFMAINX and the decoder.

Thanks to Kevin Gosse!
https://github.com/upx/upx/pull/716
https://github.com/MichalStrehovsky/PublishAotCompressed/issues/11
2023-10-06 14:14:32 -07:00
Markus F.X.J. Oberhumer e32de83758 CI updates 2023-10-05 12:23:17 +02:00
Markus F.X.J. Oberhumer e767461f65 src: more clang-format 2023-10-05 11:53:02 +02:00
Markus F.X.J. Oberhumer 632c7c4826 all: assorted cleanups; introduce undocumented '--sysinfo' option 2023-10-05 03:51:27 +02:00
Markus F.X.J. Oberhumer 7f9d381c7b CI updates 2023-09-30 10:46:39 +02:00
Markus F.X.J. Oberhumer 4d5d6661d5 submodules: update for new versions 2023-09-30 09:44:58 +02:00
John Reiser b0b87eda02 check-whitespace
modified:   stub/src/upxfd_android.c
2023-09-28 12:49:14 -07:00
John Reiser f63a673a8b Prepare to emulate memfd_create() on 32-bit Android (ARM and i386)
modified:   stub/src/include/linux.h
	new file:   stub/src/upxfd_android.c
	new file:   stub/src/upxfd_create.c
2023-09-28 12:44:49 -07:00
John Reiser 290dd0c5d2 Git straggler
modified:   src/stub/tmp/i386-linux.elf-entry.bin.dump
2023-09-28 12:09:32 -07:00
John Reiser 194bf2b852 Common prototypes for mmap and ftruncate
modified:   src/stub/src/include/linux.h
	modified:   src/stub/src/amd64-linux.elf-so_main.c
	modified:   src/stub/src/i386-linux.elf-so_main.c
	modified:   src/stub/src/i386-linux.elf.execve-main.c
	modified:   src/stub/src/i386-linux.elf.interp-main.c
	modified:   src/stub/src/i386-linux.elf.shell-main.c
2023-09-28 12:07:04 -07:00
John Reiser d6d5e7ae3d For Android emulator: align i386 LEXEC020 binfo
modified:   src/stub/src/i386-linux.elf-entry.S
	modified:   src/p_lx_elf.cpp

	modified:   src/stub/i386-linux.elf-entry.h
	modified:   misc/testsuite/upx_testsuite_1-expected_sha256sums.sh
2023-09-28 12:02:28 -07:00
Markus F.X.J. Oberhumer 39a6cc4b5f src: improve memory sanitizer handling 2023-09-26 15:15:55 +02:00
Markus F.X.J. Oberhumer a24de15060 submodules: update for new versions 2023-09-26 15:15:55 +02:00
Markus F.X.J. Oberhumer eb021accd1 CI updates 2023-09-25 13:47:43 +02:00
Markus F.X.J. Oberhumer 98a77dde00 CI updates 2023-09-22 17:33:22 +02:00
John Reiser 854988bc5f Detect AlreadyPacked even when trailing PackHeader has been lopped.
This is heuristic, but strong.
https://github.com/upx/upx/issues/712
	modified:   p_lx_elf.cpp
	modified:   p_unix.h
2023-09-21 14:12:18 -07:00
John Reiser bfeed2ab9a MAP_PRIVATE to capture memfd pages before closing the fd
https://github.com/upx/upx/issues/710

	modified:   stub/src/amd64-linux.elf-so_main.c
	modified:   stub/src/i386-linux.elf-so_main.c

	modified:   stub/amd64-linux.elf-so_fold.h
	modified:   stub/arm.v4a-linux.elf-so_fold.h
	modified:   stub/arm.v5a-linux.elf-so_fold.h
	modified:   stub/arm64-linux.elf-so_fold.h
	modified:   stub/i386-linux.elf-so_fold.h
2023-09-20 13:12:04 -07:00
Markus F.X.J. Oberhumer d11fc71e79 CI updates 2023-09-20 11:24:55 +02:00
Markus F.X.J. Oberhumer f1703fa322 CI updates 2023-09-19 11:47:15 +02:00
Markus F.X.J. Oberhumer 06675acc67 all: cosmetic cleanups 2023-09-18 15:19:37 +02:00
Markus F.X.J. Oberhumer 57ad6bc37d CI updates 2023-09-11 06:52:57 +02:00
dependabot[bot] 0192b0b7e4 build(deps): bump actions/checkout from 3 to 4 (#707)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-06 18:54:02 +02:00
Markus F.X.J. Oberhumer 3b098b845a CI updates 2023-09-06 12:48:30 +02:00
Markus F.X.J. Oberhumer ac398f1ffe CI updates 2023-09-06 01:48:20 +02:00
Markus F.X.J. Oberhumer 92dfb9c83c testsuite: add file system test suite test_symlinks.sh 2023-09-06 00:09:44 +02:00
Markus F.X.J. Oberhumer 38d6cb090c src/packer.cpp: fix bug in constructor introduced during cleanup
Introduced in 10e759f1f1
2023-09-05 21:09:17 +02:00
Markus F.X.J. Oberhumer e93172bd33 src/work.cpp: clean up get_open_flags() 2023-09-05 06:09:13 +02:00
Markus F.X.J. Oberhumer 30fcca4b64 src: optimize preserve_link: only if the file has actual link-count >= 2 2023-09-05 05:50:47 +02:00
Markus F.X.J. Oberhumer 4f6320d3aa src: add new option --link to preserve hard links; use with care 2023-09-04 22:34:21 +02:00
Markus F.X.J. Oberhumer 62dbf8485f src: sort cleanups 2023-09-04 07:28:48 +02:00
John Reiser 9331ed39d4 32-bit Android lacks memfd_create, and has varying __NR_ftruncate
https://github.com/upx/upx/issues/700
	modified:   stub/src/i386-linux.elf-so_main.c
	modified:   stub/src/arm.v4a-linux.elf-so_entry.S
	modified:   stub/src/arm.v4a-linux.elf-so_fold.S

	modified:   stub/arm.v4a-linux.elf-so_entry.h
	modified:   stub/arm.v4a-linux.elf-so_fold.h
	modified:   stub/arm.v5a-linux.elf-so_entry.h
	modified:   stub/arm.v5a-linux.elf-so_fold.h
2023-09-02 15:31:32 -07:00
Markus F.X.J. Oberhumer 35dd9cfd22 src: retract libc qsort() requirements 2023-09-02 16:15:57 +02:00
Markus F.X.J. Oberhumer 0ac6c36af2 src: add a check for libc qsort(); cleanups 2023-09-01 11:59:29 +02:00
Markus F.X.J. Oberhumer 3c4b959f78 all: update clang-format settings 2023-09-01 11:29:51 +02:00
Markus F.X.J. Oberhumer a00687b092 src/p_mach.cpp: make sort order deterministic 2023-09-01 11:11:00 +02:00
Markus F.X.J. Oberhumer bb6b087862 src: implement upx_shellsort() 2023-09-01 10:49:47 +02:00
John Reiser bfb438dc89 Sync stubs
modified:   stub/amd64-linux.elf-so_fold.h
	modified:   stub/arm.v4a-linux.elf-so_fold.h
	modified:   stub/arm.v5a-linux.elf-so_fold.h
	modified:   stub/arm64-linux.elf-so_fold.h
	modified:   stub/i386-linux.elf-so_fold.h
	modified:   stub/tmp/amd64-linux.elf-so_fold.bin.dump
2023-08-31 13:34:49 -07:00
John Reiser cd3f69c290 Explicit write() can subsume ftruncate()
modified:   stub/src/amd64-linux.elf-so_main.c
	modified:   stub/src/i386-linux.elf-so_main.c
2023-08-31 13:25:53 -07:00
Markus F.X.J. Oberhumer d54315392e src: add support for NO_COLOR environment variable 2023-08-31 12:31:31 +02:00
Markus F.X.J. Oberhumer cfa8107ab9 src: make sort order deterministic, next try
We cannot compare pointers as they may point to qsort-local objects.
And we must make sure that cmp(a,b) always agrees with cmp(b,a).
2023-08-30 16:41:59 +02:00
Markus F.X.J. Oberhumer f4e5b29708 src: make sort order deterministic 2023-08-28 02:08:34 +02:00
Markus F.X.J. Oberhumer d65fea1147 src/bele.h: try to detect possible size-mismatches 2023-08-28 00:23:53 +02:00
Markus F.X.J. Oberhumer 25a3c109c1 CI updates 2023-08-27 13:30:51 +02:00
John Reiser b526eed346 Detect "no Shdrs" earlier when already packed
https://github.com/upx/upx/issues/699
	modified:   p_lx_elf.cpp
2023-08-23 19:52:35 +02:00
John Reiser 59c6a71b72 More use of ph_forced_method()
modified:   p_lx_elf.cpp
2023-08-23 19:52:35 +02:00
John Reiser c7a2a0faa1 Document path to mach-o/loader.h on Apple CommandLineTools
modified:   p_mach_enum.h
2023-08-23 19:52:35 +02:00
John Reiser bfb5ea50a9 Temporary
modified:   p_lx_elf.cpp
2023-08-23 19:52:35 +02:00
John Reiser 149d84edca --brute versus forced_method(ph.method)
https://github.com/upx/upx/issues/694  (partial)
	modified:   p_lx_elf.cpp
2023-08-23 19:52:35 +02:00
Markus F.X.J. Oberhumer 7636abc158 CI updates 2023-08-22 11:12:48 +02:00
Markus F.X.J. Oberhumer 6eace187e7 src: add a famous quote 2023-08-22 00:37:45 +02:00
Markus F.X.J. Oberhumer dd1838a7eb src: minor cleanups 2023-08-21 22:41:42 +02:00
Markus F.X.J. Oberhumer dd928cf956 src: update MemBuffer::getSizeForCompression() 2023-08-21 22:32:28 +02:00
Markus F.X.J. Oberhumer 38be230467 submodules: update for new versions 2023-08-21 22:28:25 +02:00
Markus F.X.J. Oberhumer 1f747a28a9 all: spell check 2023-08-17 12:55:38 +02:00
Markus F.X.J. Oberhumer 1a7732b285 CI update: add ASAN/MSAN/valgrind checks 2023-08-17 12:07:19 +02:00
Markus F.X.J. Oberhumer f8ea416a4d src/pefile.cpp: fix a pedantic ASAN error 2023-08-17 00:08:03 +02:00
Markus F.X.J. Oberhumer b9bf81d548 src/p_lx_elf.cpp: init o_binfo to avoid crash with MSAN build
This should be double-checked by @jreiser
2023-08-16 22:23:28 +02:00
Markus F.X.J. Oberhumer 8975e2a6b5 src: create util/cxxlib.h 2023-08-16 10:05:59 +02:00
Markus F.X.J. Oberhumer 394cd77bec all: cleanups 2023-08-16 01:06:52 +02:00
Markus F.X.J. Oberhumer a9ac4b5e23 src: introduce type tribool 2023-08-15 14:44:50 +02:00
Markus F.X.J. Oberhumer 10e759f1f1 src: minor cleanups 2023-08-11 13:32:53 +02:00
Markus F.X.J. Oberhumer 777d4f5279 src: refactoring: create packhead.h and move some methods 2023-08-11 03:57:20 +02:00
Markus F.X.J. Oberhumer c65c882ecc src: class Packer decomposition, introduce PackerBase 2023-08-10 20:40:27 +02:00
Markus F.X.J. Oberhumer a66ee9fafd CI update 2023-08-09 21:08:04 +02:00
Markus F.X.J. Oberhumer 757401dd0c CI and spell checks 2023-08-09 13:08:38 +02:00
Markus F.X.J. Oberhumer 11e3770864 CI updates 2023-08-08 15:57:45 +02:00
Markus F.X.J. Oberhumer fbb317e9c8 submodules: update for new versions 2023-08-08 12:54:11 +02:00
Markus F.X.J. Oberhumer 9d7698a359 testsuite: update checksums caused by version bump 2023-08-08 12:46:17 +02:00
Markus F.X.J. Oberhumer 44fd11f4dd all: post-release version bump 2023-08-08 12:43:47 +02:00
Markus F.X.J. Oberhumer 8779113131 all: prepare for release 2023-08-08 10:38:12 +02:00
Markus F.X.J. Oberhumer 26cfd0a616 all: minor cleanups 2023-08-08 10:34:12 +02:00
John Reiser 75e153dd99 More care in ::forward_Shdrs() and ::pack4()
Also, de-compressing arm64 shlib restores .init_array[0],
although supposedly *_RELATIVE relocation should overwrite.

https://github.com/upx/upx/issues/693
	modified:   p_lx_elf.cpp
	modified:   p_lx_elf.h
2023-08-04 11:52:58 -07:00
Markus F.X.J. Oberhumer fa364d6ea3 all: final cleanups in preparation for release 2023-08-03 14:20:35 +02:00
Markus F.X.J. Oberhumer 13e5c13695 Fix functional change in commit 905bfacf44 2023-08-02 17:45:17 +02:00
John Reiser 43b3b54197 spell check typos
modified:   p_lx_exc.cpp
	modified:   p_mach.cpp
	modified:   stub/src/amd64-linux.elf-so_main.c
	modified:   stub/src/i386-linux.elf-so_main.c
	modified:   stub/src/arch/mips/r3000/bits.ash
	modified:   stub/src/arm.v4a-linux.elf-fold.S
	modified:   stub/src/arm.v4a-linux.shlib-init.S
	modified:   stub/src/arm64-linux.shlib-init.S
	modified:   stub/src/i386-linux.elf-main.c
	modified:   stub/src/mipsel.r3000-linux.elf-entry.S
2023-07-31 09:05:32 -07:00
John Reiser 3a16d4a12e Spell check; No-Functional-Change
modified:   p_lx_elf.cpp
2023-07-31 06:06:31 -07:00
Markus F.X.J. Oberhumer 50fc9235de misc: update podman test-qemu 2023-08-01 07:24:10 +02:00
Markus F.X.J. Oberhumer 70287d3c49 clang-tidy 2023-07-31 14:49:48 +02:00
John Reiser 41e9f7985f forward_Shdrs: elfout for main, lowmem for shlib
Especially Android.
https://github.com/upx/upx/issues/680
	modified:   p_lx_elf.cpp
	modified:   p_lx_elf.h
2023-07-29 13:43:33 -07:00
John Reiser c3327977da Pwrite:
modified:   stub/src/amd64-linux.elf-so_fold.S

	modified:   stub/amd64-linux.elf-so_fold.h
	modified:   stub/tmp/amd64-linux.elf-so_fold.bin.dump
2023-07-29 13:42:20 -07:00
John Reiser 905bfacf44 Pacify clang-tidy 2023-07-26 17:21:39 -07:00
Markus F.X.J. Oberhumer 053e95033f all: improve C++ static analyzers 2023-07-26 22:28:47 +02:00
Markus F.X.J. Oberhumer 5a1203be0d submodules: update for new versions 2023-07-26 18:13:25 +02:00
John Reiser 745fef7425 fpad4, fpad8, and _Shdr hacking should guard against (!fo)
Also pacify some clang scan-build complaints.
	modified:   p_lx_elf.cpp
2023-07-26 07:27:12 -07:00
John Reiser c9d625a237 Use 'elfout' for changing ElfXX_Ehdr
https://github.com/upx/upx/issues/688
	modified:   p_lx_elf.cpp
2023-07-26 07:15:22 +02:00
John Reiser 334731f56b Sync stubs for powerpc64le-linux.elf/upx-3.95
How did this mismatch happen?
	modified:   ../misc/testsuite/upx_testsuite_1-expected_sha256sums.sh
	modified:   stub/arm64-linux.elf-so_entry.h
	modified:   stub/powerpc64-linux.elf-fold.h
	modified:   stub/powerpc64le-linux.elf-fold.h
2023-07-26 07:15:22 +02:00
John Reiser d5e7672a45 De-activate "bkpt" at entry
modified:   arm64-linux.elf-so_entry.S
2023-07-26 07:15:22 +02:00
Markus F.X.J. Oberhumer e702aa0252 Review 2023-07-26 07:15:22 +02:00
John Reiser 2684e815e0 Fix use of memfd_create for shlib stubs, espcially Android
Also relocation of init_array[0] for Elf32 shlib.
        https://github.com/upx/upx/issues/220
        https://github.com/upx/upx/issues/609
        https://github.com/upx/upx/issues/680

	modified:   stub/src/amd64-linux.elf-so_main.c
	modified:   stub/src/i386-linux.elf-so_main.c
	modified:   p_lx_elf.cpp

	modified:   stub/src/arm.v4a-linux.elf-so_fold.S
	modified:   stub/src/arm64-linux.elf-so_entry.S
	modified:   stub/src/arm64-linux.elf-so_fold.S
	modified:   stub/src/i386-linux.elf-so_fold.S

	modified:   stub/amd64-linux.elf-so_fold.h
	modified:   stub/arm.v4a-linux.elf-so_fold.h
	modified:   stub/arm.v5a-linux.elf-so_fold.h
	modified:   stub/arm64-linux.elf-so_entry.h
	modified:   stub/arm64-linux.elf-so_fold.h
	modified:   stub/i386-linux.elf-so_fold.h
	modified:   stub/tmp/amd64-linux.elf-so_fold.bin.dump
2023-07-26 07:15:22 +02:00
John Reiser efbc93229a Un-debug amd64-linux.elf-so_main.c
modified:   stub/src/amd64-linux.elf-so_main.c

	modified:   stub/amd64-linux.elf-so_fold.h
	modified:   stub/arm64-linux.elf-so_fold.h
	modified:   stub/tmp/amd64-linux.elf-so_fold.bin.dump
2023-07-26 07:15:22 +02:00
John Reiser 05539ad5b6 Fix stubs for shlib with only 2 PT_LOAD 2023-07-26 07:15:22 +02:00
John Reiser 670aae2e11 Check /proc/self/auxv exists
modified:   stub/src/amd64-linux.elf-so_main.c
	modified:   stub/src/i386-linux.elf-so_main.c

	modified:   stub/amd64-linux.elf-so_fold.h
	modified:   stub/arm.v4a-linux.elf-so_fold.h
	modified:   stub/arm.v5a-linux.elf-so_fold.h
	modified:   stub/arm64-linux.elf-so_fold.h
	modified:   stub/tmp/amd64-linux.elf-so_fold.bin.dump
2023-07-26 07:15:22 +02:00
John Reiser e6ff68dc2c Turn on DEBUG for 64-bit shlib
modified:   src/stub/src/amd64-linux.elf-so_main.c

	modified:   src/stub/amd64-linux.elf-so_fold.h
	modified:   src/stub/arm64-linux.elf-so_fold.h
	modified:   src/stub/tmp/amd64-linux.elf-so_fold.bin.dump
2023-07-26 07:15:22 +02:00
Markus F.X.J. Oberhumer 641b116f04 Update .gitattributes. 2023-07-25 12:18:33 +02:00
Markus F.X.J. Oberhumer f81f7194ed submodules: update for new versions 2023-07-25 12:05:14 +02:00
Markus F.X.J. Oberhumer 161d20e614 CI: update 2023-07-24 14:47:32 +02:00
Markus F.X.J. Oberhumer fc4dcd46db CI and build updates 2023-07-22 16:12:13 +02:00
Markus F.X.J. Oberhumer 891dc87064 misc: upx_testsuite; move podman directories into subdirectory 2023-07-22 00:19:11 +02:00
Markus F.X.J. Oberhumer b866631448 misc: improve upx_testsuite; cmake update 2023-07-19 20:12:20 +02:00
John Reiser 672d69c68a Fix unpacking of upx-3.94-armeb_linux/upx
Getting past the code of the stub must deal with variances
between released versions.
	modified:   p_lx_elf.cpp
2023-07-18 16:56:39 -07:00
Markus F.X.J. Oberhumer 507c31ec14 CI and cmake updates 2023-07-18 07:21:51 +02:00
John Reiser 65cc40bdda Align escape hatch in powerpc64 main program
modified:   stub/src/amd64-linux.elf-main.c
	modified:   ../misc/testsuite/upx_testsuite_1-expected_sha256sums.sh

	modified:   stub/powerpc64-linux.elf-fold.h
	modified:   stub/powerpc64le-linux.elf-fold.h
	modified:   stub/tmp/powerpc64-linux.elf-fold.map
	modified:   stub/tmp/powerpc64le-linux.elf-fold.map
2023-07-17 15:58:01 -07:00
John Reiser 067895fa5f Fix brk+munmap in folded stubs for main programs
qemu emulating a compressed ET_EXEC revealed an access to ElfXX_Phdr
on the discarded side of brk() during cleanup. qemu was more aggressive
than the Linux kernel implementation of brk().
        https://github.com/upx/upx/issues/683

	modified:   stub/src/i386-linux.elf-main.c
	modified:   stub/src/include/linux.h

	modified:   ../misc/testsuite/upx_testsuite_1-expected_sha256sums.sh

	modified:   stub/src/amd64-linux.elf-fold.S
	modified:   stub/src/arm.v4a-linux.elf-fold.S
	modified:   stub/src/arm64-linux.elf-fold.S
	modified:   stub/src/i386-linux.elf-fold.S
	modified:   stub/src/mipsel.r3000-linux.elf-fold.S
	modified:   stub/src/powerpc-linux.elf-fold.S
	modified:   stub/src/powerpc64le-linux.elf-fold.S

	modified:   stub/amd64-linux.elf-fold.h
	modified:   stub/arm.v4a-linux.elf-fold.h
	modified:   stub/arm.v5a-linux.elf-fold.h
	modified:   stub/arm64-linux.elf-fold.h
	modified:   stub/armeb.v4a-linux.elf-fold.h
	modified:   stub/i386-linux.elf-fold.h
	modified:   stub/mips.r3000-linux.elf-fold.h
	modified:   stub/mipsel.r3000-linux.elf-fold.h
	modified:   stub/powerpc-linux.elf-fold.h
	modified:   stub/powerpc64-linux.elf-fold.h
	modified:   stub/powerpc64le-linux.elf-fold.h

	modified:   stub/tmp/amd64-linux.elf-fold.map
	modified:   stub/tmp/arm.v4a-linux.elf-fold.map
	modified:   stub/tmp/arm.v5a-linux.elf-fold.map
	modified:   stub/tmp/arm64-linux.elf-fold.map
	modified:   stub/tmp/armeb.v4a-linux.elf-fold.map
	modified:   stub/tmp/i386-linux.elf-fold.map
	modified:   stub/tmp/mips.r3000-linux.elf-fold.map
	modified:   stub/tmp/mipsel.r3000-linux.elf-fold.map
	modified:   stub/tmp/powerpc-linux.elf-fold.map
	modified:   stub/tmp/powerpc64-linux.elf-fold.map
	modified:   stub/tmp/powerpc64le-linux.elf-fold.map
2023-07-17 07:21:56 +02:00
Markus F.X.J. Oberhumer 3f7f26c74b CI: update 2023-07-16 21:28:26 +02:00
Markus F.X.J. Oberhumer 9a6b5940cf CI: update 2023-07-16 15:14:19 +02:00
Markus F.X.J. Oberhumer 828f4a63bf src: add some "explicit"; cleanups 2023-07-16 07:37:31 +02:00
John Reiser 707fb55625 A fuzzer attacked i386-dos32.watcom.le 2023-07-06 20:25:14 -07:00
Markus F.X.J. Oberhumer 8d41ae09c8 all: misc updates 2023-07-12 18:59:08 +02:00
Markus F.X.J. Oberhumer 7ec0faca1e all: misc and noexcept updates 2023-07-09 17:36:24 +02:00
Markus F.X.J. Oberhumer 300fa29446 CI: update 2023-07-08 21:28:29 +02:00
Markus F.X.J. Oberhumer 6981f7b3ae misc: add misc/test-qemu-with-podman 2023-07-08 18:14:41 +02:00
Markus F.X.J. Oberhumer 682a1e97e4 src: add assert_noexcept() 2023-07-08 12:06:27 +02:00
Markus F.X.J. Oberhumer 1d71dd3851 all: clang-tidy updates 2023-07-08 10:51:02 +02:00
Markus F.X.J. Oberhumer 5edfda46e5 all: clang-tidy updates 2023-07-08 09:59:41 +02:00
Markus F.X.J. Oberhumer d7754a97c7 all: add support for clang-tidy 2023-07-07 23:13:08 +02:00
Markus F.X.J. Oberhumer c79aa6ad8a all: cosmetic updates 2023-07-06 18:03:37 +02:00
Markus F.X.J. Oberhumer 525e091472 src/console: disable win32 screen driver when running under Wine 2023-07-06 10:09:38 +02:00
Markus F.X.J. Oberhumer 16f6de677d misc: podman updates 2023-07-06 10:09:38 +02:00
John Reiser 12c36bab6c Linux EINVAL for zero-length mmap: mmap(, 0, ,,,)
https://github.com/upx/upx/issues/681
	modified:   stub/src/amd64-linux.elf-main.c
	modified:   stub/src/i386-linux.elf-main.c

	modified:   stub/src/i386-bsd.elf-main.c
	modified:   stub/src/i386-openbsd.elf-main.c

	modified:   ../misc/testsuite/upx_testsuite_1-expected_sha256sums.sh

	modified:   stub/amd64-linux.elf-fold.h
	modified:   stub/arm64-linux.elf-fold.h
	modified:   stub/i386-bsd.elf-fold.h
	modified:   stub/i386-linux.elf-fold.h
	modified:   stub/i386-netbsd.elf-fold.h
	modified:   stub/i386-openbsd.elf-fold.h
	modified:   stub/mips.r3000-linux.elf-fold.h
	modified:   stub/mipsel.r3000-linux.elf-fold.h
	modified:   stub/powerpc-linux.elf-fold.h
	modified:   stub/powerpc64-linux.elf-fold.h
	modified:   stub/powerpc64le-linux.elf-fold.h
	modified:   stub/tmp/amd64-linux.elf-fold.map
	modified:   stub/tmp/arm64-linux.elf-fold.map
	modified:   stub/tmp/i386-bsd.elf-fold.map
	modified:   stub/tmp/i386-linux.elf-fold.map
	modified:   stub/tmp/i386-netbsd.elf-fold.map
	modified:   stub/tmp/i386-openbsd.elf-fold.map
	modified:   stub/tmp/mips.r3000-linux.elf-fold.map
	modified:   stub/tmp/mipsel.r3000-linux.elf-fold.map
	modified:   stub/tmp/powerpc-linux.elf-fold.map
	modified:   stub/tmp/powerpc64-linux.elf-fold.map
	modified:   stub/tmp/powerpc64le-linux.elf-fold.map
2023-07-06 10:09:07 +02:00
John Reiser c429859cbf Placate Android dlopen() some more.
https://github.com/upx/upx/issues/680
	modified:   p_lx_elf.cpp
2023-07-06 10:08:41 +02:00
John Reiser dc76b2af97 info(Android_penalty)
modified:   p_lx_elf.cpp
2023-06-26 09:09:47 -07:00
Markus F.X.J. Oberhumer b75e7687f4 all: CI and misc updates 2023-06-30 01:20:48 +02:00
Markus F.X.J. Oberhumer ece5af2895 CI: make sure that directories which contain whitespace do work 2023-06-28 18:18:36 +02:00
Markus F.X.J. Oberhumer 1aaa33552e all: move testsuite to misc/testsuite; CI updates 2023-06-27 14:27:19 +02:00
Markus F.X.J. Oberhumer f622871eb0 src: fix building under freebsd; updates 2023-06-27 12:59:24 +02:00
Markus F.X.J. Oberhumer 060b01260d CI: yet more updates 2023-06-25 19:40:09 +02:00
Markus F.X.J. Oberhumer 871f8a4793 src: new ACC version 2023-06-25 14:30:00 +02:00
Markus F.X.J. Oberhumer c54e03d0f2 CI: ongoing cleanups 2023-06-25 03:27:51 +02:00
Markus F.X.J. Oberhumer aaf3f75990 CI and cmake updates 2023-06-25 01:55:06 +02:00
Markus F.X.J. Oberhumer 512a26cee4 CI: update 2023-06-24 10:16:43 +02:00
John Reiser b4a793ed26 Make ::forward_Shdrs more friendly to Android dlopen()
https://github.com/upx/upx/issues/220
https://github.com/upx/upx/issues/609
2023-06-22 10:16:25 -07:00
Markus F.X.J. Oberhumer 5d2c74008e all: cmake and noexcept updates 2023-06-23 14:13:08 +02:00
Markus F.X.J. Oberhumer 7fafc68940 CI: update 2023-06-19 14:28:12 +02:00
Markus F.X.J. Oberhumer d1af2af499 all: yet more misc updates 2023-06-15 19:42:54 +02:00
Markus F.X.J. Oberhumer a5206eb696 CI: cleanups 2023-06-14 07:40:14 +02:00
Markus F.X.J. Oberhumer 1ff0d137ab all: misc updates 2023-06-13 16:42:14 +02:00
John Reiser 07aa65b55e Sync stubs
Dependency processing does not propagate this one:
src/stub/src/arm.v5a-darwin.macho-main.c:
   #include "amd64-darwin.macho-main.c"
	modified:   arm.v5a-darwin.macho-fold.h
	modified:   tmp/arm.v5a-darwin.macho-fold.map
2023-06-13 16:29:13 +02:00
John Reiser 0fadddec65 Force 'bkpt' on arm.v5a and below
fixup  https://github.com/upx/upx/issues/612
	modified:   stub/src/amd64-darwin.macho-main.c
2023-06-13 16:29:13 +02:00
John Reiser 1bebe53cef Allow more bytes for Mach_headers in /usr/lib/dyld on MacOS 13
Fixes initial complaint (HelloUPX4) in https://github.com/upx/upx/issues/612
	modified:   stub/amd64-darwin.macho-fold.h
	modified:   stub/arm64-darwin.macho-fold.h
	modified:   stub/src/amd64-darwin.macho-fold.S
	modified:   stub/src/amd64-darwin.macho-main.c
	modified:   stub/tmp/amd64-darwin.macho-fold.map
	modified:   stub/tmp/arm64-darwin.macho-fold.map
2023-06-13 16:29:13 +02:00
John Reiser 43019c744c Document requirement for 'homebrew' when developing on MacOS
... else testsuite fails for "readlink -en" and 'sha256sum'
https://github.com/upx/upx/issues/676
	modified:   README.SRC
2023-06-13 16:29:13 +02:00
Markus F.X.J. Oberhumer c585774162 CI: disable self-test on macos-13 2023-06-10 11:02:19 +02:00
Markus F.X.J. Oberhumer 75e87a58da src: rework mem_clear() 2023-06-09 18:20:06 +02:00
Markus F.X.J. Oberhumer 19e84fea62 all: yet more minor updates 2023-06-09 14:12:05 +02:00
Markus F.X.J. Oberhumer db39f9c4dc all: CI and misc updates 2023-06-06 23:16:28 +02:00
Markus F.X.J. Oberhumer dae45ae0d4 all: bump version; cleanups 2023-05-28 14:06:11 +02:00
Markus F.X.J. Oberhumer efeffc6e01 submodules: update for new versions 2023-05-28 13:58:27 +02:00
Markus F.X.J. Oberhumer ebf0f2f68a all: more minor cleanups 2023-05-27 22:58:07 +02:00
Markus F.X.J. Oberhumer 09bd1d8c40 all: misc updates 2023-05-19 13:21:26 +02:00
Markus F.X.J. Oberhumer 40653e40a4 all: minor cleanups 2023-05-14 09:36:10 +02:00
Markus F.X.J. Oberhumer b3e4efbabe all: misc updates 2023-05-13 16:28:44 +02:00
John Reiser 279101d464 Fix checksum of non-compressible extents
https://github.com/upx/upx/issues/673
	modified:   src/p_unix.cpp
2023-05-13 16:28:22 +02:00
Markus F.X.J. Oberhumer f571feee72 CI: use gcc -static for macos builds 2023-05-10 20:42:26 +02:00
Markus F.X.J. Oberhumer 900afd1c8c all: minor updates 2023-05-10 20:20:39 +02:00
Markus F.X.J. Oberhumer 08a72d5251 Fix whitespace. 2023-05-10 20:19:22 +02:00
John Reiser 736a6cd955 Catch amd64 ET_EXEC with .e_entry < 0x400000
https://github.com/upx/upx/issues/673
	modified:   p_lx_elf.cpp
2023-05-10 20:17:22 +02:00
John Reiser 75ce5e5df3 Fix SIGSEGV due to name confusion in ::forward_Shdrs
https://github.com/upx/upx/issues/671
	modified:   p_lx_elf.cpp
2023-05-10 20:17:22 +02:00
Markus F.X.J. Oberhumer eaf2143162 CI: add macos-13 2023-05-03 10:06:22 +02:00
Markus F.X.J. Oberhumer f0bdb8dea1 submodules: update for new versions 2023-05-03 09:49:20 +02:00
John Reiser 60093cfff6 Merge branch 'devel4' of https://github.com/upx/upx into devel4 2023-04-30 15:19:44 -07:00
John Reiser 56bb7b53cb Synch *.h stub headers and testcase checksums
Shared libraries for amd64, i386, arm64, and arm should be
compatible with SELinux: no complaints of execmod or execmem.

https://github.com/upx/upx/issues/609
https://github.com/upx/upx/issues/220
	modified:   ../.github/travis_testsuite_1-expected_sha256sums.sh
	modified:   stub/amd64-linux.elf-so_entry.h
	modified:   stub/amd64-linux.elf-so_fold.h
	modified:   stub/arm.v4a-linux.elf-so_entry.h
	modified:   stub/arm.v4a-linux.elf-so_fold.h
	modified:   stub/arm.v5a-linux.elf-entry.h
	modified:   stub/arm.v5a-linux.elf-fold.h
	modified:   stub/arm.v5a-linux.elf-so_entry.h
	modified:   stub/arm.v5a-linux.elf-so_fold.h
	modified:   stub/arm64-linux.elf-so_entry.h
	modified:   stub/arm64-linux.elf-so_fold.h
	modified:   stub/i386-linux.elf-so_entry.h
	modified:   stub/i386-linux.elf-so_fold.h
	modified:   stub/tmp/amd64-linux.elf-so_entry.bin.dump
	modified:   stub/tmp/amd64-linux.elf-so_fold.bin.dump
	modified:   stub/tmp/arm.v5a-linux.elf-entry.bin.dump
	modified:   stub/tmp/arm.v5a-linux.elf-fold.map
2023-04-30 15:12:29 -07:00
John Reiser 0cffeca102 arm32 shlib works with SELinux
modified:   stub/src/arch/arm/v4a/macros.S
	modified:   stub/src/arm.v4a-linux.elf-so_entry.S
	modified:   stub/src/arm.v4a-linux.elf-so_fold.S
	modified:   stub/src/arm64-linux.elf-so_entry.S
	modified:   stub/src/i386-linux.elf-so_main.c
2023-04-28 13:52:26 -07:00
John Reiser 937d4462ca SELinux for i386 shlib stub
modified:   stub/src/i386-linux.elf-so_entry.S
	modified:   stub/src/i386-linux.elf-so_fold.S
	modified:   stub/src/i386-linux.elf-so_main.c
	modified:   stub/src/include/linux.h
2023-04-27 18:49:35 -07:00
John Reiser db5a39572c Change stub for arm64 shlib to work with SELinux
modified:   stub/src/arm64-linux.elf-so_entry.S
	modified:   stub/src/arm64-linux.elf-so_fold.S
2023-04-27 10:44:13 -07:00
John Reiser ecc9c67e1f Check return value from syscalls; leave debugging hint if error
modified:   stub/src/amd64-linux.elf-so_entry.S
2023-04-27 10:42:56 -07:00
John Reiser 0901ce1b68 amd64-linux.elf shlib now fully-SELinux compliant
modified:   stub/src/amd64-linux.elf-so_entry.S
	modified:   stub/src/amd64-linux.elf-so_fold.S
2023-04-26 13:06:48 -07:00
John Reiser be6e77379a SELinux forces memfd_create for .so on amd64, arm64
More coming for .so: so_entry.S, powerpc64, 32-bit
	modified:   stub/src/amd64-linux.elf-so_main.c
	modified:   stub/src/arm64-linux.elf-so_entry.S
	modified:   stub/src/arm64-linux.elf-so_fold.S
2023-04-26 08:30:55 -07:00
Markus F.X.J. Oberhumer 726f5de778 src: minor cleanups 2023-04-26 08:13:32 +02:00
John Reiser 98b835e0a7 WIP: SELinux is expensive: +2KB in stub
Needs make_hatch()
	modified:   stub/src/amd64-linux.elf-so_main.c
	modified:   stub/src/amd64-linux.elf-so_fold.S

	modified:   stub/amd64-linux.elf-so_fold.h
	modified:   stub/arm64-linux.elf-so_fold.h
	modified:   stub/src/arm.v4a-linux.elf-so_fold.S
	modified:   stub/tmp/amd64-linux.elf-so_fold.bin.dump
2023-04-24 19:40:57 -07:00
John Reiser 04ffb641a6 Compilers generate junk .sh_info
modified:   p_lx_elf.cpp
2023-04-24 19:37:25 -07:00
John Reiser 1b7233b673 whitespace
modified:   stub/src/amd64-expand.S
2023-04-24 19:35:52 -07:00
John Reiser eaa0f33473 Fix call to unfilter from amd64-expand
modified:   stub/src/amd64-expand.S

	modified:   stub/amd64-linux.elf-fold.h
	modified:   stub/amd64-linux.elf-so_fold.h
	modified:   stub/tmp/amd64-linux.elf-fold.map
	modified:   stub/tmp/amd64-linux.elf-so_fold.bin.dump
2023-04-21 08:57:10 -07:00
Markus F.X.J. Oberhumer c03b382d61 src: some more "noexcept" 2023-04-20 20:58:19 +02:00
Markus F.X.J. Oberhumer e633694255 cmake: use MSVC_FRONTEND 2023-04-20 20:10:12 +02:00
Markus F.X.J. Oberhumer 278b25bad2 cmake: check CMAKE_C_COMPILER_FRONTEND_VARIANT 2023-04-20 14:54:14 +02:00
Markus F.X.J. Oberhumer f89f0838dc src: change UPX_CONFIG logic to permissive defaults 2023-04-20 14:13:36 +02:00
Markus F.X.J. Oberhumer b1729e3bcf src: cleanup MAX_ELF_HDR 2023-04-19 23:23:46 +02:00
Markus F.X.J. Oberhumer d1ab85a1a6 src: cleanup linker.h 2023-04-19 23:19:45 +02:00
John Reiser 7f5b64c91a Merge branch 'devel4' of https://github.com/upx/upx into devel4 2023-04-19 14:00:43 -07:00
John Reiser 78b68283c4 Fix .e_entry for PowerPC64
https://github.com/upx/upx/issues/668
	modified:   p_lx_elf.cpp
2023-04-19 13:58:52 -07:00
Markus F.X.J. Oberhumer 9e3b1c9f8a src: enable TE checks in packer.h; add some "noexcept" 2023-04-18 17:56:28 +02:00
Markus F.X.J. Oberhumer 5dc54c7adc Merge branch 'devel' into devel4 2023-04-18 17:15:57 +02:00
Markus F.X.J. Oberhumer 320e5b850f all: yet more cleanups
Changes include:
  - use standard names for PE constants
  - add some more "noexcept"
  - improve upx_is_integral type-trait
  - introduce is_same_all and is_same_any type-traits
  - prepare TE-size checks in packer.h
  - CI updates
2023-04-18 17:02:13 +02:00
John Reiser d8395d8c42 Fix usage of _te32/_te64/_te16 for Elf classes
How did it ever work?  UPX_RSIZE_MAX_MEM of 768MiB, Elf32_Off of only
32-bits, and preponderance of little-endian and small positive integers
hides many mis-uses of _te64/_te32.
ELF does not help: e_phnum, e_shnum, Elf32_Section, Elf64_Section are all
16-bit, but sh_info and sh_link are 32-bit.
Templatizing p_elf.h (following the example of p_mach.h) failed
because of complexity.  (Plus too many special cases of ELF where 32-bit
and 64-bit are not parallel.)
	modified:   p_lx_elf.cpp
	modified:   p_lx_sh.cpp
	modified:   p_mach.cpp
2023-04-17 13:19:06 -07:00
John Reiser a20c5a1e7f Align 64-bit forward_Shdr
//github.com/upx/upx/issues/220
	modified:   p_lx_elf.cpp
2023-04-12 14:54:49 -07:00
John Reiser 3bdfcaa541 Try to placate Android crapware, which cannot deal with null strings
From https://github.com/upx/upx/issues/220 :

Phone:
04-10 16:07:52.862 E/AndroidRuntime( 5178): java.lang.UnsatisfiedLinkError: dlopen failed: \
"/data/app/~~Nwb-iR6LHpHyrT37xe8HNg==/com.android.support-y0YbcwLn1b4sBRD09JGVAw==/lib/arm64/libMyLibName.so" \
has unsupported e_shentsize: 0x0 (expected 0x40)

Emulator:
04-10 09:57:38.746 E/AndroidRuntime( 6403): java.lang.UnsatisfiedLinkError: dlopen failed: \
"/data/app/~~sBBMDvh36TxwO4muxOJ3Bg==/com.android.support-8Lc6r2dLzTIW7SEHXLI0XQ==/lib/arm64/libMyLibName.so" \
has no section headers

	modified:   p_lx_elf.cpp
2023-04-11 13:41:54 -07:00
John Reiser 7b2faf2016 Elf64_Rela for shlib DT_INIT_ARRAY
Also allow PT_PHDR in shlibs.
Also page align lo end of mmap, like mprotect.
        https://github.com/upx/upx/issues/664
	modified:   p_lx_elf.cpp
	modified:   stub/src/amd64-linux.elf-so_main.c
	modified:   stub/src/i386-linux.elf-so_main.c

	modified:   stub/src/amd64-linux.elf-so_fold.S
	modified:   stub/src/arm.v4a-linux.elf-fold.S
	modified:   stub/src/arm.v4a-linux.elf-so_fold.S
	modified:   stub/src/arm64-linux.elf-fold.S
	modified:   stub/src/arm64-linux.elf-so_fold.S
	modified:   stub/src/i386-linux.elf-so_fold.S

	modified:   stub/amd64-linux.elf-so_fold.h
	modified:   stub/arm.v4a-linux.elf-fold.h
	modified:   stub/arm.v4a-linux.elf-so_fold.h
	modified:   stub/arm.v5a-linux.elf-fold.h
	modified:   stub/arm.v5a-linux.elf-so_fold.h
	modified:   stub/arm64-linux.elf-fold.h
	modified:   stub/arm64-linux.elf-so_fold.h
	modified:   stub/armeb.v4a-linux.elf-fold.h
	modified:   stub/i386-linux.elf-so_fold.h

	modified:   stub/tmp/amd64-linux.elf-so_fold.bin.dump
	modified:   stub/tmp/arm.v4a-linux.elf-fold.map
	modified:   stub/tmp/arm.v5a-linux.elf-fold.map
	modified:   stub/tmp/arm64-linux.elf-fold.map
	modified:   stub/tmp/armeb.v4a-linux.elf-fold.map

	modified:   stub/src/arch/mips/r3000/macros.ash
	modified:   ../.github/travis_testsuite_1-expected_sha256sums.sh
2023-04-11 11:00:48 -07:00
John Reiser 42902dabac 64-bit shlib with DT_INIT_ARRAY but no DT_INIT
https://github.com/upx/upx/issues/664
	modified:   p_elf_enum.h
	modified:   p_lx_elf.cpp
2023-04-10 18:01:39 -07:00
John Reiser 14521eb6dd Allow pre-linking when compressing shared libraries
Such as Wine kernel32.dll etc.
https://github.com/upx/upx/issues/660
	modified:   stub/amd64-linux.elf-so_fold.h
	modified:   stub/arm.v4a-linux.elf-so_fold.h
	modified:   stub/arm.v5a-linux.elf-so_fold.h
	modified:   stub/arm64-linux.elf-so_fold.h
	modified:   stub/i386-linux.elf-so_fold.h
	modified:   stub/src/amd64-linux.elf-so_main.c
	modified:   stub/src/i386-linux.elf-so_main.c
	modified:   stub/tmp/amd64-linux.elf-so_fold.bin.dump
2023-04-03 13:18:21 -07:00
John Reiser b9533f409c Sync testsuite checksums
modified:   ../.github/travis_testsuite_1-expected_sha256sums.sh
2023-03-29 16:11:08 -07:00
John Reiser 4df68aafd2 Pprotect: mprotect but enlarge the interval to start on page boundary
https://github.com/upx/upx/issues/609
	modified:   src/stub/src/amd64-linux.elf-fold.S
	modified:   src/stub/src/amd64-linux.elf-main.c
	modified:   src/stub/src/amd64-linux.elf-so_fold.S
	modified:   src/stub/src/amd64-linux.elf-so_main.c
	modified:   src/stub/src/arm.v4a-linux.elf-fold.S
	modified:   src/stub/src/arm.v4a-linux.elf-so_fold.S
	modified:   src/stub/src/arm64-linux.elf-fold.S
	modified:   src/stub/src/arm64-linux.elf-so_fold.S
	modified:   src/stub/src/i386-linux.elf-fold.S
	modified:   src/stub/src/i386-linux.elf-main.c
	modified:   src/stub/src/i386-linux.elf-so_fold.S
	modified:   src/stub/src/i386-linux.elf-so_main.c
	modified:   src/stub/src/mipsel.r3000-linux.elf-fold.S
	modified:   src/stub/src/powerpc-linux.elf-fold.S
	modified:   src/stub/src/powerpc64le-linux.elf-fold.S

	modified:   src/stub/amd64-linux.elf-fold.h
	modified:   src/stub/amd64-linux.elf-so_fold.h
	modified:   src/stub/arm.v4a-linux.elf-fold.h
	modified:   src/stub/arm.v4a-linux.elf-so_fold.h
	modified:   src/stub/arm.v5a-linux.elf-fold.h
	modified:   src/stub/arm.v5a-linux.elf-so_fold.h
	modified:   src/stub/arm64-linux.elf-fold.h
	modified:   src/stub/arm64-linux.elf-so_fold.h
	modified:   src/stub/armeb.v4a-linux.elf-fold.h
	modified:   src/stub/i386-linux.elf-fold.h
	modified:   src/stub/i386-linux.elf-so_fold.h
	modified:   src/stub/mips.r3000-linux.elf-fold.h
	modified:   src/stub/mipsel.r3000-linux.elf-fold.h
	modified:   src/stub/powerpc-linux.elf-fold.h
	modified:   src/stub/powerpc64-linux.elf-fold.h
	modified:   src/stub/powerpc64le-linux.elf-fold.h

	modified:   src/stub/tmp/amd64-linux.elf-fold.map
	modified:   src/stub/tmp/amd64-linux.elf-so_fold.bin.dump
	modified:   src/stub/tmp/arm.v4a-linux.elf-fold.map
	modified:   src/stub/tmp/arm.v5a-linux.elf-fold.map
	modified:   src/stub/tmp/arm64-linux.elf-fold.map
	modified:   src/stub/tmp/armeb.v4a-linux.elf-fold.map
	modified:   src/stub/tmp/i386-linux.elf-fold.map
	modified:   src/stub/tmp/mips.r3000-linux.elf-fold.map
	modified:   src/stub/tmp/mipsel.r3000-linux.elf-fold.map
	modified:   src/stub/tmp/powerpc-linux.elf-fold.map
	modified:   src/stub/tmp/powerpc64-linux.elf-fold.map
	modified:   src/stub/tmp/powerpc64le-linux.elf-fold.map
2023-03-29 15:46:58 -07:00
John Reiser c72ceaa979 MSVC
modified:   p_lx_elf.cpp
2023-03-26 11:29:19 -07:00
John Reiser 8ac79ca0ad whitespce
modified:   p_lx_elf.cpp
2023-03-26 11:16:36 -07:00
John Reiser e0bfaf1028 Merge branch 'devel4' of https://github.com/upx/upx into devel4 2023-03-26 11:06:22 -07:00
John Reiser b361b91ec7 Try to appease Android runtime loader; _Shdr vs _Phdr offsets
JNI FalalError called: Unable to load library:
    [dlopen failed: "/lib/arm/libunity.so"
    .dynamic section has invalid offset: 0x6d3e58,
    expected to match PT_DYNAMIC offset: 0x441e58]
https://github.com/upx/upx/issues/609
	modified:   p_elf_enum.h
	modified:   p_lx_elf.cpp
2023-03-26 10:53:30 -07:00
John Reiser b5d1eba4c1 mprotect() requires page-aligned address
modified:   stub/amd64-linux.elf-so_fold.h
	modified:   stub/arm.v4a-linux.elf-so_fold.h
	modified:   stub/arm.v5a-linux.elf-so_fold.h
	modified:   stub/arm64-linux.elf-so_fold.h
	modified:   stub/i386-linux.elf-so_fold.h
	modified:   stub/src/amd64-linux.elf-so_fold.S
	modified:   stub/src/arm.v4a-linux.elf-so_entry.S
	modified:   stub/src/arm.v4a-linux.elf-so_fold.S
	modified:   stub/src/arm64-linux.elf-so_fold.S
	modified:   stub/src/i386-linux.elf-so_fold.S
	modified:   stub/tmp/amd64-linux.elf-so_fold.bin.dump
2023-03-26 07:26:53 -07:00
John Reiser ba447344d6 New strategy for de-compression stub for shared libraries
modified:   stub/src/amd64-linux.elf-so_main.c
	modified:   stub/src/i386-linux.elf-so_main.c
2023-03-26 07:25:32 -07:00
John Reiser 7b68aa7bdc Fix de-comression of shared libraries
modified:   p_elf_enum.h
	modified:   p_lx_elf.cpp
	modified:   p_lx_elf.h
2023-03-26 07:23:08 -07:00
John Reiser 5d15e57294 De-compression for 32-bit shared libraries on i686, ARM
https://github.com/upx/upx/issues/609
	modified:   p_lx_elf.cpp
	modified:   p_lx_elf.h
2023-03-23 16:29:25 -07:00
John Reiser 0bf8ff151e Un-debug stubs for 32-bit shared libraries
modified:   stub/arm.v4a-linux.elf-so_fold.h
	modified:   stub/arm.v5a-linux.elf-so_fold.h
	modified:   stub/i386-linux.elf-so_fold.h
	modified:   stub/src/arm.v4a-linux.elf-so_entry.S
2023-03-23 16:27:44 -07:00
John Reiser 06fae05910 32-bit ARM Android shlib: DT_INIT_ARRAY without DT_INIT
De-compressor needs to catch up.
	modified:   p_elf_enum.h
	modified:   p_lx_elf.cpp
	modified:   p_lx_elf.h
	modified:   stub/src/i386-linux.elf-so_main.c
2023-03-22 10:44:17 -07:00
Markus F.X.J. Oberhumer f68ac8155b Merge branch 'devel' into devel4 2023-03-18 21:52:17 +01:00
Markus F.X.J. Oberhumer 15484aa296 all: more cleanups
Changes include:
  - extract headers.h from conf.h
  - use "byte" in some more places
  - unify "const" coding style
  - pefile.cpp: make sort order deterministic
  - simplify some other pefile.cpp code
  - CI updates
2023-03-18 21:27:34 +01:00
John Reiser 5b113a5041 Merge branch 'devel4' of https://github.com/upx/upx into devel4 2023-03-16 08:51:29 -07:00
John Reiser 1320e3efdb PackLinuxElf32::canPackOSABI() isolates canPack() from OSABI weirdness
modified:   p_lx_elf.cpp
	modified:   p_lx_elf.h
2023-03-16 08:30:06 -07:00
Markus F.X.J. Oberhumer d32f447bda Merge branch 'devel' into devel4 2023-03-15 22:34:05 +01:00
John Reiser b74c4e4ac1 Picky, picky static analyzer
https://github.com/upx/upx/actions/runs/4422867763/jobs/7755057541
	modified:   p_lx_elf.cpp
2023-03-15 09:05:02 -07:00
John Reiser 35333403ef Zero ElfXX_Ehdr.e_sh* info when removing ElfXX_Shdr
The aim is less confusion by static linkers: the _Shdr are gone!
https://github.com/upx/upx/issues/659
	modified:   p_lx_elf.cpp
2023-03-15 08:44:59 -07:00
Markus F.X.J. Oberhumer a627648249 all: assorted cleanups and updates
Changes include:
  - add a bunch of "noexcept", mostly to operators and forceinline
  - use "uchar"
  - use "charptr"
  - rename options_t to Options
  - add ptr_check_no_overlap()
  - rewrite p_exe.cpp, NFCI
  - clang-format help.cpp
  - spelling fixes
2023-03-15 00:19:55 +01:00
Markus F.X.J. Oberhumer 127fd095e7 CI: add spell-check.yml 2023-03-11 03:11:19 +01:00
John Reiser f8934c09ff F*ck MSVC
warning C4245: 'return': conversion from 'int' to 'unsigned int', signed/unsigned mismatch
    return ~0;  // in function declared as returning 'unsigned'.  The bits are the same!
	modified:   p_lx_elf.cpp
2023-03-09 12:00:56 -08:00
John Reiser 7a09c88e30 CI convention sucks
renamed:    MAX_ELF_HDR.cpp -> MAX_ELF_HDR.h
	modified:   p_lx_elf.cpp
2023-03-09 11:44:22 -08:00
John Reiser 17526d1132 Make it easier to change MAX_ELF_HDR consistently
https://github.com/upx/upx/issues/655

	new file:   MAX_ELF_HDR.cpp
	new file:   stub/src/MAX_ELF_HDR.S
	new file:   stub/src/MAX_ELF_HDR.c

	modified:   p_lx_elf.cpp
	modified:   stub/arm.v4a-linux.elf-fold.h
	modified:   stub/arm64-linux.elf-fold.h
	modified:   stub/src/amd64-linux.elf-fold.S
	modified:   stub/src/amd64-linux.elf-main.c
	modified:   stub/src/amd64-linux.elf-so_main.c
	modified:   stub/src/arm.v4a-linux.elf-fold.S
	modified:   stub/src/arm.v4a-linux.elf-so_fold.S
	modified:   stub/src/arm64-linux.elf-fold.S
	modified:   stub/src/arm64-linux.elf-so_fold.S
	modified:   stub/src/i386-bsd.elf-fold.S
	modified:   stub/src/i386-bsd.elf-main.c
	modified:   stub/src/i386-linux.elf-fold.S
	modified:   stub/src/i386-linux.elf-main.c
	modified:   stub/src/i386-linux.elf-so_main.c
	modified:   stub/src/i386-linux.elf.interp-fold.S
	modified:   stub/src/i386-linux.elf.interp-main.c
	modified:   stub/src/i386-linux.elf.shell-fold.S
	modified:   stub/src/i386-linux.elf.shell-main.c
	modified:   stub/src/i386-openbsd.elf-fold.S
	modified:   stub/src/i386-openbsd.elf-main.c
	modified:   stub/src/mipsel.r3000-linux.elf-fold.S
	modified:   ../.github/travis_testsuite_1-expected_sha256sums.sh
2023-03-09 10:06:13 -08:00
John Reiser ff7939c1c0 invert_pt_dynamic, sort_DTxx_offsets, elf_find_table_size
https://github.com/upx/upx/issues/655
        modified:   p_lx_elf.cpp
        modified:   p_lx_elf.h
2023-03-09 09:24:35 -08:00
John Reiser 96c196b1be Final ph.u_len and ph.c_len reflect multiple compressed extents
https://github.com/upx/upx/issues/655
	modified:   ../.github/travis_testsuite_1-expected_sha256sums.sh
	modified:   p_lx_elf.cpp
2023-03-09 09:06:06 -08:00
John Reiser adb0ca8250 Many changes for ELF shared libraries on Linux and Android
Handling more than 2 PT_LOAD (and thus more than 1 executable PT_LOAD)
required extensive changes.  But the bonus is the infrastructure
to support a different (de-)compression algorithm for each PT_LOAD.

https://github.com/upx/upx/issues/341   i386 .so decompression
https://github.com/upx/upx/issues/609   armv7 .so on Android
https://github.com/upx/upx/issues/625   amd64 .so execution
https://github.com/upx/upx/issues/654   armv7 .exe
Not yet: .so on MIPS, PowerPC, PowerPC64
2023-03-04 17:37:25 -08:00
Markus F.X.J. Oberhumer fa56a1d9cd submodules: update for new versions 2023-02-24 10:59:32 +01:00
Markus F.X.J. Oberhumer 3d691645a4 src: pefile: add checkMachine() 2023-02-21 20:33:40 +01:00
Markus F.X.J. Oberhumer e1edc5f50a src: use 'byte' instead of 'upx_byte'; NFCI 2023-02-21 19:27:23 +01:00
Markus F.X.J. Oberhumer 4a8efd2e2f src: rework optimizeReloc handling; cleanups 2023-02-21 15:19:24 +01:00
Markus F.X.J. Oberhumer 8d364c82e2 CI: add build for windows arm64ec 2023-02-12 19:27:56 +01:00
Markus F.X.J. Oberhumer c5059231dc all: rename win32/arm back to wince/arm 2023-02-12 18:58:11 +01:00
Markus F.X.J. Oberhumer f584c91386 all: canonicalize win32 and win64 file names 2023-02-10 09:49:29 +01:00
Markus F.X.J. Oberhumer b8d9c2b755 all: assorted updates and cleanups 2023-02-05 17:20:32 +01:00
Markus F.X.J. Oberhumer 163377d1a0 testsuite: update checksums caused by version bump 2023-01-30 13:44:18 +01:00
Markus F.X.J. Oberhumer 8944e90175 all: post-release version bump 2023-01-30 13:39:49 +01:00
438 changed files with 42009 additions and 20907 deletions
+7 -1
View File
@@ -8,6 +8,7 @@ IndentWidth: 4
---
Language: Cpp
AccessModifierOffset: -4
AlignConsecutiveMacros: AcrossComments
AlwaysBreakTemplateDeclarations: true
AttributeMacros:
- __acc_cdecl
@@ -16,10 +17,15 @@ AttributeMacros:
- __acc_cdecl_sighandler
- __acc_forceinline
- __acc_noinline
- __acc_static_noinline
- __acc_static_forceinline
- __acc_static_noinline
- DELETED_FUNCTION
- XSPAN_DELETED_FUNCTION
- forceinline
- may_throw
- noinline
- static_forceinline
- static_noinline
EmptyLineBeforeAccessModifier: Leave
SortIncludes: false
SpaceAfterCStyleCast: true
+30
View File
@@ -0,0 +1,30 @@
# for clang-tidy-16 from https://clang.llvm.org/extra/clang-tidy/
---
Checks: >
-*,
bugprone-*,
-bugprone-assignment-in-if-condition,
-bugprone-branch-clone,
-bugprone-easily-swappable-parameters,
-bugprone-empty-catch,
-bugprone-implicit-widening-of-multiplication-result,
-bugprone-macro-parentheses,
-bugprone-narrowing-conversions,
-bugprone-reserved-identifier,
-bugprone-sizeof-expression,
-bugprone-suspicious-include,
-bugprone-suspicious-memory-comparison,
-bugprone-suspicious-string-compare,
-bugprone-switch-missing-default-case,
clang-analyzer-*,
-clang-analyzer-optin.performance.Padding,
-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,
-clang-analyzer-security.insecureAPI.strcpy,
clang-diagnostics-*',
performance-*,
-performance-avoid-endl,
-performance-unnecessary-value-param,
FormatStyle: file
HeaderFilterRegex: '.*'
InheritParentConfig: false
...
+25 -7
View File
@@ -1,10 +1,28 @@
# make GitHub language detection more accurate, see https://github.com/github/linguist
# see https://github.com/github-linguist/linguist
#
# HINT: check settings with
# git ls-files | git check-attr --stdin --all
src/*.h linguist-language=C++
src/*/*.h linguist-language=C++
#
# tell diff tools that these files are generated automatically
#
src/stub/**/*.ash linguist-language=Assembly
src/stub/**/*.asm linguist-language=Assembly
src/stub/**/*.S linguist-language=Assembly
/doc/upx.1 linguist-generated
/doc/upx-doc.* linguist-generated
src/stub/tmp/** linguist-vendored
/src/stub/*.h linguist-generated
/src/stub/src/arch/**/lzma_d_c[fns].S linguist-generated
/src/stub/tmp/** linguist-generated
#
# make GitHub language detection more accurate
#
/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
+11
View File
@@ -0,0 +1,11 @@
* @markus-oberhumer @jreiser
/src/p_elf* @jreiser
/src/p_lx_* @jreiser
/src/p_mach* @jreiser
/src/p_unix* @jreiser
/src/p_vmlin* @jreiser
/src/stub/src/*bsd.* @jreiser
/src/stub/src/*darwin.* @jreiser
/src/stub/src/*linux.* @jreiser
+3 -2
View File
@@ -4,5 +4,6 @@ updates:
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
# Check for updates to GitHub Actions every weekday
interval: 'daily'
# Check for updates to GitHub Actions every Wednesday
interval: 'weekly'
day: 'wednesday'
@@ -1,209 +0,0 @@
########## 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
-290
View File
@@ -1,290 +0,0 @@
#! /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
+43
View File
@@ -0,0 +1,43 @@
# see https://github.com/crate-ci/typos
# a generic spell-checker that works on source code is quite
# tricky, so some false positives are fine
[files]
extend-exclude = ["LICENSE", "misc/*podman*/*/packages.txt"]
# misc variable names & symbols
[default.extend-identifiers]
acc_spawnve = "acc_spawnve"
ba = "ba"
fo = "fo"
fof = "fof"
O_WRONLY = "O_WRONLY"
# optin: clang-analyzer-optin.cplusplus
optin = "optin"
sidelen = "sidelen"
# macOS 11 "Big Sur"
Sur = "Sur"
tpos = "tpos"
# assembly sources
hda = "hda"
Larg = "Larg"
pard = "pard"
suble = "suble"
# identifiers are intelligently split into words and then checked again
[default.extend-words]
delt = "delt"
FO = "FO"
fo = "fo"
# parm is used like param
PARM = "PARM"
parm = "parm"
# rela: ELF relocations
RELA = "RELA"
rela = "rela"
# siz is used for size
siz = "siz"
# SEH: Structured Exception Handling
SEH = "SEH"
seh = "seh"
+146 -85
View File
@@ -1,4 +1,4 @@
# Support for GitHub Actions -- https://github.com/features/actions
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
# note: GitHub Actions runner images are frequently updated, and
# unfortunately this sometimes breaks builds in mysterious ways...
@@ -9,8 +9,12 @@ name: 'CI'
on: [push, workflow_dispatch]
env:
CMAKE_REQUIRED_QUIET: "OFF"
CTEST_OUTPUT_ON_FAILURE: "ON"
DEBIAN_FRONTEND: noninteractive
UPX_CMAKE_BUILD_FLAGS: --verbose
# 2023-10-24
ZIG_DIST_VERSION: 0.12.0-dev.1245+a07f288eb
jobs:
job-rebuild-and-verify-stubs:
@@ -21,17 +25,24 @@ jobs:
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'
if ! test -e /usr/bin/python2; then
####sudo apt-get update && sudo apt-get install -y --no-install-recommends python2-minimal
# install python2-minimal packages from Debian-11
wget -q 'https://ftp.debian.org/debian/pool/main/p/python2.7/libpython2.7-minimal_2.7.18-8_amd64.deb'
wget -q 'https://ftp.debian.org/debian/pool/main/p/python2.7/python2.7-minimal_2.7.18-8_amd64.deb'
sudo dpkg -i ./*python2*.deb && rm ./*python2*.deb && sudo ldconfig
sudo ln -s -v python2.7 /usr/bin/python2
fi
# manually unpack and install compat libs from Ubuntu-16.04
wget -q 'https://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
# install upx-stubtools
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
uses: actions/checkout@v4
with: { submodules: true }
- name: 'Rebuild and verify stubs'
run: |
@@ -46,7 +57,8 @@ jobs:
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:
job-linux-cmake: # uses cmake + make
if: true
needs: [ job-rebuild-and-verify-stubs ]
name: ${{ format('{0} cmake', matrix.os) }}
runs-on: ${{ matrix.os }}
@@ -55,7 +67,7 @@ jobs:
matrix:
include:
- { os: ubuntu-22.04, use_m32: true }
- { os: ubuntu-20.04, use_m32: false }
- { os: ubuntu-20.04, use_m32: false } # use_m32 also works here, but save some CI time
steps:
- name: 'Install extra 32-bit and Windows packages'
if: ${{ matrix.use_m32 }}
@@ -64,7 +76,7 @@ jobs:
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
uses: actions/checkout@v4
with: { submodules: true }
- name: 'Check out test suite'
run: 'git clone --depth=1 https://github.com/upx/upx-testsuite ../deps/upx-testsuite'
@@ -90,7 +102,7 @@ jobs:
run: 'make build/extra/cross-windows-mingw64/release'
- name: 'Make artifact'
run: |
N=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-${{ matrix.os }}
N=$(echo "upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-${{ matrix.os }}" | sed 's/[^0-9a-zA-Z_.-]/-/g')
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")
@@ -101,6 +113,10 @@ jobs:
with:
name: ${{ env.artifact_name }}
path: tmp/artifact
- name: 'Run install tests'
run: |
(cd build/extra/gcc/release && DESTDIR=$PWD/Install-with-cmake cmake --install .)
(cd build/extra/gcc/release && DESTDIR=$PWD/Install-with-make make install)
- name: 'Run basic tests'
run: |
make -C build/extra/gcc/debug test
@@ -112,13 +128,17 @@ jobs:
run: |
make -C build/extra/gcc-m32/debug test
make -C build/extra/gcc-m32/release test
- name: 'Run file system test suite'
run: |
env -C build/extra/gcc/release bash "$PWD"/misc/testsuite/test_symlinks.sh
- 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)
testsuite_1="$(readlink -en ./misc/testsuite/upx_testsuite_1.sh)"
env -C build/extra/gcc/release upx_exe=./upx bash "$testsuite_1"
job-macos-cmake:
job-macos-cmake: # uses cmake + make
if: true
needs: [ job-rebuild-and-verify-stubs ]
name: ${{ format('{0} cmake', matrix.os) }}
runs-on: ${{ matrix.os }}
@@ -126,16 +146,23 @@ jobs:
fail-fast: false
matrix:
include:
# NOTE: macos does not have "env -C"; only with coreutils
# NOTE: macos-11 does not have "readlink -f"; only on macos >= 12 or with coreutils
- { os: macos-11, gcc: gcc-10, gxx: 'g++-10', testsuite: true }
- { os: macos-12, gcc: gcc-11, gxx: 'g++-11', testsuite: true }
- { os: macos-13, gcc: gcc-12, gxx: 'g++-12', testsuite: true }
steps:
- name: 'Install brew packages'
if: ${{ matrix.testsuite }}
run: |
brew update
brew install coreutils
# testsuite needs working "readlink -en" and "sha256sum -b"
if ! test -e /usr/local/opt/coreutils/libexec/gnubin/readlink; then
echo "===== brew leaves:"; brew leaves; echo "===== brew list:"; brew list
# only run "brew update" if needed
if ! brew install coreutils; then brew update && brew install coreutils; fi
fi
- name: 'Check out code'
uses: actions/checkout@v3
uses: actions/checkout@v4
with: { submodules: true }
- name: 'Check out test suite'
if: ${{ matrix.testsuite }}
@@ -146,10 +173,10 @@ jobs:
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 }}'
run: 'make build/extra/gcc/debug CC="${{ matrix.gcc }} -static-libgcc" CXX="${{ matrix.gxx }} -static-libgcc -static-libstdc++"'
- name: 'Build cmake extra/gcc/release'
if: ${{ matrix.gcc != '' }}
run: 'make build/extra/gcc/release CC=${{ matrix.gcc }} CXX=${{ matrix.gxx }}'
run: 'make build/extra/gcc/release CC="${{ matrix.gcc }} -static-libgcc" CXX="${{ matrix.gxx }} -static-libgcc -static-libstdc++"'
- name: 'Build cmake xtarget/cross-darwin-arm64/debug'
run: |
CC="clang -target arm64-apple-darwin" CXX="clang++ -target arm64-apple-darwin" \
@@ -160,7 +187,7 @@ jobs:
make UPX_XTARGET=cross-darwin-arm64 xtarget/release
- name: 'Make artifact'
run: |
N=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-${{ matrix.os }}
N=$(echo "upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-${{ matrix.os }}" | sed 's/[^0-9a-zA-Z_.-]/-/g')
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")
@@ -171,45 +198,53 @@ jobs:
with:
name: ${{ env.artifact_name }}
path: tmp/artifact
- name: 'Run install tests'
run: |
(cd build/extra/clang/release && DESTDIR=$PWD/Install-with-cmake cmake --install .)
(cd build/extra/clang/release && DESTDIR=$PWD/Install-with-make make install)
- name: 'Run basic tests'
if: ${{ !contains(matrix.os, 'macos-13') }} # FIXME: UPX on macos-13 is broken => disable self-test for now
run: |
make -C build/extra/clang/debug test
make -C build/extra/clang/release test
# make -C build/extra/clang/release test
- name: 'Run file system test suite'
if: ${{ matrix.testsuite }} # for coreutils readlink
run: |
## macos-11 does not have "readlink -f"
## testsuite="$(readlink -fn ./misc/testsuite/test_symlinks.sh)"
## (cd build/extra/clang/release && upx_exe=./upx bash "$testsuite")
export PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"
env -C build/extra/clang/release bash "$PWD"/misc/testsuite/test_symlinks.sh
- 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)
testsuite_1="$(readlink -en ./misc/testsuite/upx_testsuite_1.sh)"
env -C build/extra/clang/release upx_exe=./upx bash "$testsuite_1"
job-windows-cmake:
job-windows-cmake: # uses cmake + msbuild
if: true
needs: [ job-rebuild-and-verify-stubs ]
name: ${{ format('{0} cmake', matrix.os) }}
name: ${{ format('{0} cmake', matrix.name) }}
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 }
- { name: windows-2019-amd64, os: windows-2019, vsversion: 2019, arch: amd64 }
- { name: windows-2022-amd64, os: windows-2022, vsversion: 2022, arch: amd64 }
steps:
- name: 'Check out code'
uses: actions/checkout@v3
uses: actions/checkout@v4
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: 'Set up Developer Command Prompt'
uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1
with:
vsversion: ${{ matrix.vsversion }}
arch: ${{ matrix.arch }}
- name: 'Build cmake debug'
run: 'make build/debug'
- name: 'Build cmake release'
@@ -217,7 +252,7 @@ jobs:
- name: 'Make artifact'
shell: bash
run: |
N=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-${{ matrix.os }}
N=$(echo "upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-${{ matrix.os }}" | sed 's/[^0-9a-zA-Z_.-]/-/g')
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
@@ -228,82 +263,95 @@ jobs:
name: ${{ env.artifact_name }}
path: tmp/artifact
- name: 'Run basic tests'
if: ${{ matrix.arch != 'amd64_arm64' }}
run: |
cmake --build build/debug --config Debug --target RUN_TESTS
cmake --build build/release --config Release --target RUN_TESTS
ctest --test-dir build/debug -C Debug
ctest --test-dir build/release -C Release
- name: 'Run test suite build/release'
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)
testsuite_1="$(readlink -en ./misc/testsuite/upx_testsuite_1.sh)"
env -C build/release/Release upx_exe=./upx bash "$testsuite_1"
job-windows-toolchains:
job-windows-toolchains: # build "by hand" using cmd.exe
if: true
needs: [ job-rebuild-and-verify-stubs ]
name: ${{ format('windows {0}', matrix.name) }}
runs-on: ${{ matrix.os }}
env:
C: ${{ matrix.C }}
C: ${{ matrix.name }}
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 }
- { name: amd64-win64-vs2019, os: windows-2019, vsversion: 2019, arch: amd64 }
- { name: amd64-win64-vs2022, os: windows-2022, vsversion: 2022, arch: amd64 }
- { name: arm64-win64-vs2019, os: windows-2019, vsversion: 2019, arch: amd64_arm64 }
- { name: arm64-win64-vs2022, os: windows-2022, vsversion: 2022, arch: amd64_arm64 }
- { name: arm64ec-win64-vs2022, os: windows-2022, vsversion: 2022, arch: amd64_arm64, cl_machine_flags: -arm64EC, link_machine_flags: '/machine:arm64ec' }
# { name: arm64x-win64-vs2022, os: windows-2022, vsversion: 2022, arch: amd64_arm64, cl_machine_flags: -arm64EC, link_machine_flags: '/machine:arm64x' }
- { name: i386-win32-vs2019, os: windows-2019, vsversion: 2019, arch: amd64_x86 }
- { name: i386-win32-vs2022, os: windows-2022, vsversion: 2022, arch: amd64_x86 }
steps:
- name: 'Check out code'
uses: actions/checkout@v3
uses: actions/checkout@v4
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}
mkdir -p -v build/$C/$B/{bzip2,ucl,upx,zlib,zstd}
- name: 'Set up Developer Command Prompt'
uses: ilammy/msvc-dev-cmd@v1
uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1
with:
vsversion: ${{ matrix.vsversion }}
arch: ${{ matrix.arch }}
- name: 'Build'
- name: 'Build by hand'
shell: cmd
run: |
@REM setup directories
@REM ===== set vars =====
where cl & where link
set RUN_CL=cl ${{ matrix.cl_machine_flags }} -MT
set RUN_LIB=link -lib ${{ matrix.link_machine_flags }}
set DEFS=-D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -DWIN32_LEAN_AND_MEAN
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 bzip2 =====
cd %BDIR%\bzip2
@rem %RUN_CL% -J -O2 -W4 -wd4127 -wd4244 -wd4267 -WX %DEFS% -c %H%\vendor\bzip2\*.c
@rem %RUN_LIB% -out:bzip2.lib *.obj
@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
%RUN_CL% -J -O2 -W4 -WX %DEFS% -I%s%\include -I%s% -c %s%\src\*.c
%RUN_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
%RUN_CL% -J -O2 -W3 -WX %DEFS% -DHAVE_VSNPRINTF -c %H%\vendor\zlib\*.c
%RUN_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
cd %BDIR%\zstd
set s=%H%\vendor\zstd\lib
@rem %RUN_CL% -J -O2 -W4 -WX %DEFS% -DDYNAMIC_BMI2=0 -DZSTD_DISABLE_ASM -c %s%\common\*.c %s%\compress\*.c %s%\decompress\*.c
@rem %RUN_LIB% -out:zstd.lib *.obj
@REM ===== build UPX =====
cd %BDIR%\upx
set s=%H%\src
cat .GITREV.txt
set /p GITREV=<.GITREV.txt
set UPX_DEFS=-DUPX_CONFIG_DISABLE_WSTRICT=0 -DUPX_CONFIG_DISABLE_WERROR=0 -DWITH_BZIP2=0 -DWITH_ZSTD=0
set UPX_LIBS=%BDIR%\ucl\ucl.lib %BDIR%\zlib\zlib.lib
@rem set UPX_LIBS=%BDIR%\bzip2\bzip2.lib %BDIR%\ucl\ucl.lib %BDIR%\zlib\zlib.lib %BDIR%\zstd\zstd.lib
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
%RUN_CL% -J -O2 -W4 -WX -std:c++17 -Zc:__cplusplus -EHsc -DUPX_VERSION_GITREV="""%GITREV%""" %DEFS% %UPX_DEFS% -I%H%\vendor -Feupx.exe %sources% %UPX_LIBS% /link ${{ matrix.link_machine_flags }} setargv.obj
- name: 'Make artifact'
shell: bash
run: |
N=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-windows-${{ matrix.name }}
N=$(echo "upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-windows-${{ matrix.name }}" | sed 's/[^0-9a-zA-Z_.-]/-/g')
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
@@ -331,35 +379,45 @@ jobs:
shell: bash
run: |
export upx_testsuite_SRCDIR="$(readlink -en ../deps/upx-testsuite)"
testsuite_1=$(readlink -en ./.github/travis_testsuite_1.sh)
testsuite_1="$(readlink -en ./misc/testsuite/upx_testsuite_1.sh)"
env -C build/$C/$B/upx upx_exe=./upx.exe bash "$testsuite_1"
job-linux-zigcc:
if: ${{ true }}
job-linux-zigcc: # uses cmake + make
if: github.repository_owner == 'upx'
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
container: 'alpine:3.18' # older versions such as alpine:3.12 also work; no-container also works
strategy:
fail-fast: false
matrix:
include:
# only build a few targets => more targets are tested in the Weekly CI
- { 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-linux-musl, zig_pic: -fPIE }
# { zig_target: aarch64-macos-none }
- { zig_target: aarch64-macos.11.0-none }
# { zig_target: aarch64-macos.12.0-none }
# { zig_target: aarch64-macos.13.0-none }
- { zig_target: aarch64-windows-gnu }
- { zig_target: i386-linux-musl }
- { zig_target: arm-linux-musleabihf }
# { zig_target: arm-linux-musleabihf, zig_pic: -fPIE }
# { zig_target: i386-linux-musl }
# { zig_target: i386-linux-musl, zig_pic: -fPIE }
- { zig_target: i386-windows-gnu }
# { zig_target: mips-linux-musl }
# { zig_target: mipsel-linux-musl }
# { zig_target: powerpc-linux-musl }
# { zig_target: powerpc64-linux-musl }
# { zig_target: powerpc64le-linux-musl }
- { 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-linux-musl, zig_pic: -fPIE }
# { zig_target: x86_64-macos-none }
- { zig_target: x86_64-macos.11.0-none }
# { zig_target: x86_64-macos.12.0-none }
# { zig_target: x86_64-macos.13.0-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 }}
@@ -376,7 +434,7 @@ jobs:
# 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
uses: actions/checkout@v4
with: { submodules: true }
- name: ${{ format('Install Zig {0}', env.ZIG_DIST_VERSION) }}
shell: bash
@@ -391,7 +449,7 @@ jobs:
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
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
@@ -422,7 +480,7 @@ jobs:
- 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}
N=$(echo "upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-zigcc-${{ matrix.zig_target }}${ZIG_PIC}" | sed 's/[^0-9a-zA-Z_.-]/-/g')
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")
@@ -433,5 +491,8 @@ jobs:
with:
name: ${{ env.artifact_name }}
path: tmp/artifact
# vim:set ts=2 sw=2 et:
- name: 'Run install tests'
if: ${{ contains(matrix.zig_target, '-linux') }}
run: |
(cd build/zig/${ZIG_TARGET}${ZIG_PIC}/release && DESTDIR=$PWD/Install-with-cmake cmake --install .)
(cd build/zig/${ZIG_TARGET}${ZIG_PIC}/release && DESTDIR=$PWD/Install-with-make make install)
@@ -1,3 +1,5 @@
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
# see https://docs.github.com/en/actions/managing-issues-and-pull-requests/closing-inactive-issues
# see https://github.com/actions/stale
@@ -12,22 +14,22 @@
name: 'GitHub - Close inactive issues'
on:
schedule:
- cron: '30 6 * * 4'
schedule: [cron: '50 0 * * 3'] # run weekly Wednesday 00:50 UTC
workflow_dispatch:
jobs:
close-issues:
job-close-inactive-issues:
if: github.repository_owner == 'upx'
name: 'Close inactive issues'
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v7
- uses: actions/stale@v8
with:
operations-per-run: 300
exempt-all-milestones: true
exempt-issue-labels: 'blocker,enhancement,regression'
exempt-issue-labels: 'blocker,bug,enhancement,help wanted,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.'
@@ -1,9 +1,11 @@
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
name: 'GitHub - Close pull requests'
on:
#pull_request:
workflow_dispatch:
jobs:
close-pull-requests:
job-close-pull-requests:
if: github.repository_owner == 'upx'
name: 'Close pull requests'
runs-on: ubuntu-latest
permissions:
-29
View File
@@ -1,29 +0,0 @@
# 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' }
+21
View File
@@ -0,0 +1,21 @@
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
# see https://github.com/crate-ci/typos
name: 'Misc - Spell check'
on:
schedule: [cron: '55 0 * * 3'] # run weekly Wednesday 00:55 UTC
workflow_dispatch:
env:
DEBIAN_FRONTEND: noninteractive
jobs:
job-spell-check:
if: github.repository_owner == 'upx'
name: 'Spell check'
runs-on: ubuntu-latest
steps:
- name: 'Check out code'
uses: actions/checkout@v4
with: { submodules: false }
- name: 'Spell check with crate-ci/typos'
uses: crate-ci/typos@c004e98018d8621614d1ca516eed8ca2d04b365a # v1.16.20
with: { config: ./.github/typos_config.toml }
-22
View File
@@ -1,22 +0,0 @@
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'
@@ -0,0 +1,34 @@
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
name: 'Static Analyzer - clang-analyzer'
on:
schedule: [cron: '10 4 * * 3'] # run weekly Wednesday 04:10 UTC
workflow_dispatch:
env:
CMAKE_REQUIRED_QUIET: "OFF"
CTEST_OUTPUT_ON_FAILURE: "ON"
DEBIAN_FRONTEND: noninteractive
jobs:
job-analyze-clang-analyzer: # uses cmake + make
if: github.repository_owner == 'upx'
strategy:
fail-fast: false
matrix: {container: ['alpine:3.16','alpine:3.17','alpine:3.18','alpine:edge','i386/alpine:edge']}
name: ${{ format('Analyze clang-analyzer {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 clang clang-analyzer cmake g++ git make'
- name: ${{ format('Check out UPX {0} source code', github.ref_name) }}
run: |
# this seems to be needed when running in a container (beause of UID mismatch??)
git config --global --add safe.directory '*'
git clone --branch "$GITHUB_REF_NAME" --depth 1 https://github.com/upx/upx .
git submodule update --init
- name: 'Perform clang-analyzer scan-build Analysis Debug'
run: 'make build/analyze/clang-analyzer/debug'
- name: 'Perform clang-analyzer scan-build Analysis Release'
if: success() || failure() # run this step even if the previous step failed
run: 'make build/analyze/clang-analyzer/release'
@@ -0,0 +1,34 @@
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
name: 'Static Analyzer - clang-tidy'
on:
schedule: [cron: '30 4 * * 3'] # run weekly Wednesday 04:30 UTC
workflow_dispatch:
env:
CMAKE_REQUIRED_QUIET: "OFF"
CTEST_OUTPUT_ON_FAILURE: "ON"
DEBIAN_FRONTEND: noninteractive
jobs:
job-analyze-clang-tidy: # uses cmake + make
if: github.repository_owner == 'upx'
strategy:
fail-fast: false
matrix: {container: ['alpine:3.18','alpine:edge','i386/alpine:edge']}
name: ${{ format('Analyze clang-tidy {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 clang clang-extra-tools cmake g++ git make python3'
- name: ${{ format('Check out UPX {0} source code', github.ref_name) }}
run: |
# this seems to be needed when running in a container (beause of UID mismatch??)
git config --global --add safe.directory '*'
git clone --branch "$GITHUB_REF_NAME" --depth 1 https://github.com/upx/upx .
git submodule update --init
- name: 'Perform clang-tidy Analysis Debug'
run: 'make -k build/analyze/clang-tidy/debug'
- name: 'Perform clang-tidy Analysis Release'
if: success() || failure() # run this step even if the previous step failed
run: 'make -k build/analyze/clang-tidy/release'
@@ -1,32 +1,30 @@
name: 'Static Analyzer - CodeQL'
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
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'
schedule: [cron: '50 4 * * 3'] # run weekly Wednesday 04:50 UTC
workflow_dispatch:
env:
CMAKE_REQUIRED_QUIET: "OFF"
CTEST_OUTPUT_ON_FAILURE: "ON"
DEBIAN_FRONTEND: noninteractive
jobs:
analyze:
job-analyze-codeql:
if: github.repository_owner == 'upx'
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
uses: actions/checkout@v4
with: { submodules: true }
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
+66
View File
@@ -0,0 +1,66 @@
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
# test minimal number of packages required for building UPX under Alpine Linux
# clang: apk add clang cmake make
# gcc: apk add cmake g++ make
name: 'Test - Minimal Alpine build'
on: [workflow_dispatch]
env:
CMAKE_REQUIRED_QUIET: "OFF"
CTEST_OUTPUT_ON_FAILURE: "ON"
DEBIAN_FRONTEND: noninteractive
jobs:
job-alpine-clang: # uses cmake + make
if: true
strategy: { matrix: { container: ['alpine:edge','i386/alpine:edge'] } }
name: ${{ format('clang {0}', matrix.container) }}
runs-on: ubuntu-latest
container: ${{ matrix.container }}
steps:
- name: ${{ format('Build clang {0}', matrix.container) }}
run: |
apk update && apk upgrade && apk add clang cmake make
wget https://github.com/upx/upx/releases/download/v4.1.0/upx-4.1.0-src.tar.xz
tar -xoaf upx-*-src.tar.xz
cd upx-*-src
make build/debug CC="clang -static" CXX="clang++ -static"
make build/release CC="clang -static" CXX="clang++ -static"
make -C build/debug test
make -C build/release test
make -C build/release install DESTDIR="$PWD/Install"
N=$(echo "upx-test-alpine-linux-clang-${{ matrix.container }}" | sed 's/[^0-9a-zA-Z_.-]/-/g')
echo "artifact_name=$N" >> $GITHUB_ENV
- name: ${{ format('Upload artifact {0}', env.artifact_name) }}
if: ${{ !startsWith(matrix.container, 'i386/') }} # i386: missing nodejs on host
uses: actions/upload-artifact@v3
with:
name: ${{ env.artifact_name }}
path: 'upx*/build/*/upx'
job-alpine-gcc: # uses cmake + make
if: true
strategy: { matrix: { container: ['alpine:edge','i386/alpine:edge'] } }
name: ${{ format('gcc {0}', matrix.container) }}
runs-on: ubuntu-latest
container: ${{ matrix.container }}
steps:
- name: ${{ format('Build gcc {0}', matrix.container) }}
run: |
apk update && apk upgrade && apk add cmake g++ make
wget https://github.com/upx/upx/releases/download/v4.1.0/upx-4.1.0-src.tar.xz
tar -xoaf upx-*-src.tar.xz
cd upx-*-src
make build/debug CC="gcc -static" CXX="g++ -static"
make build/release CC="gcc -static" CXX="g++ -static"
make -C build/debug test
make -C build/release test
make -C build/release install DESTDIR="$PWD/Install"
N=$(echo "upx-test-alpine-linux-gcc-${{ matrix.container }}" | sed 's/[^0-9a-zA-Z_.-]/-/g')
echo "artifact_name=$N" >> $GITHUB_ENV
- name: ${{ format('Upload artifact {0}', env.artifact_name) }}
if: ${{ !startsWith(matrix.container, 'i386/') }} # i386: missing nodejs on host
uses: actions/upload-artifact@v3
with:
name: ${{ env.artifact_name }}
path: 'upx*/build/*/upx'
+133
View File
@@ -0,0 +1,133 @@
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
name: 'Test - CMake default build type'
on: [workflow_dispatch]
env:
CMAKE_REQUIRED_QUIET: "OFF"
CTEST_OUTPUT_ON_FAILURE: "ON"
DEBIAN_FRONTEND: noninteractive
jobs:
#
# single-config generators - these use and respect CMAKE_BUILD_TYPE
#
cmake-make:
runs-on: ubuntu-latest
steps:
- name: 'Check out code'
uses: actions/checkout@v4
with: { submodules: true }
- name: 'Config, build, test and install'
run: |
cmake -S . -B build/default -G "Unix Makefiles"
cmake --build build/default --parallel --verbose
ctest --test-dir build/default
(cd build/default && DESTDIR=$PWD/Install-default cmake --install .)
# "make test" also works
env -C build/default make test
# "make install" also works
env -C build/default DESTDIR=./Install-with-make make install
cmake-ninja:
runs-on: ubuntu-latest
steps:
- name: 'Check out code'
uses: actions/checkout@v4
with: { submodules: true }
- name: 'Config, build, test and install'
run: |
test -f /usr/bin/ninja || sudo apt-get install -y ninja-build
cmake -S . -B build/default -G Ninja
cmake --build build/default --parallel --verbose
ctest --test-dir build/default
(cd build/default && DESTDIR=$PWD/Install-default cmake --install .)
# "ninja test" also works
env -C build/default ninja test
# "ninja install" also works
env -C build/default DESTDIR=./Install-with-ninja ninja install
cmake-nmake:
runs-on: windows-2022
steps:
- name: 'Check out code'
uses: actions/checkout@v4
with: { submodules: true }
- name: 'Set up Developer Command Prompt'
uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1
with:
vsversion: 2022
arch: amd64
- name: 'Config, build, test and install'
run: |
cmake -S . -B build/default -G "NMake Makefiles"
cmake --build build/default --parallel --verbose
ctest --test-dir build/default
# "cmake --install" works on Windows as well, nice
env -C build/default DESTDIR=./Install-default cmake --install .
# "nmake test" also works
env -C build/default nmake test
# "nmake install" also works
env -C build/default DESTDIR=./Install-with-nmake nmake install
#
# multi-config generators - these use CMAKE_CONFIGURATION_TYPES, but the defaults seem inconsistent
# => when using multi-config generators always explicitly pass the requested build-config
#
# ninja-multi-config seems to use the *first* element of CMAKE_CONFIGURATION_TYPES; nice
cmake-ninja-multi-config:
runs-on: ubuntu-latest
steps:
- name: 'Check out code'
uses: actions/checkout@v4
with: { submodules: true }
- name: 'Config, build, test and install'
run: |
test -f /usr/bin/ninja || sudo apt-get install -y ninja-build
cmake -S . -B build/default -G "Ninja Multi-Config"
cmake --build build/default --parallel --verbose
# multi-config: ctest NEEDS a config
ctest --test-dir build/default -C Release
(cd build/default && DESTDIR=$PWD/Install-default cmake --install .)
# "ninja test" also works with multi-config
env -C build/default ninja test
# "ninja install" also works with multi-config
env -C build/default DESTDIR=./Install-with-ninja ninja install
# vsstudio-multi-config (msbuild) seems to use "Debug" by default
cmake-vsstudio-multi-config:
runs-on: windows-2022
steps:
- name: 'Check out code'
uses: actions/checkout@v4
with: { submodules: true }
- name: 'Set up Developer Command Prompt'
uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1
with:
vsversion: 2022
arch: amd64
- name: 'Config, build and test'
run: |
cmake -S . -B build/default
cmake --build build/default --parallel --verbose
# multi-config: ctest NEEDS a config
ctest --test-dir build/default -C Debug
# TODO: does cmake --install work?
# xcode-multi-config (xcodebuild) seems to use "Debug" by default, except for "cmake --install" (BUG?)
cmake-xcode-multi-config:
runs-on: macos-12
steps:
- name: 'Check out code'
uses: actions/checkout@v4
with: { submodules: true }
- name: 'Config, build, test and install'
run: |
cmake -S . -B build/default -G Xcode
cmake --build build/default --parallel --verbose
# multi-config: ctest NEEDS a config
ctest --test-dir build/default -C Debug
# BUG(?) multi-config: cmake --install defaults to "Release" !!
(cd build/default && DESTDIR=$PWD/Install-default cmake --install . --config Debug)
+16
View File
@@ -0,0 +1,16 @@
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
name: 'Test - Unused'
on: [workflow_dispatch]
env:
CMAKE_REQUIRED_QUIET: "OFF"
CTEST_OUTPUT_ON_FAILURE: "ON"
DEBIAN_FRONTEND: noninteractive
jobs:
job-unused: # uses cmake + make
if: true
runs-on: ubuntu-latest
steps:
- run: |
true
+154
View File
@@ -0,0 +1,154 @@
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
# BS BuildSystem: build "by hand" using a POSIX-compliant shell
name: 'Weekly CI BS - By Hand'
on:
schedule: [cron: '00 1 * * 3'] # run weekly Wednesday 01:00 UTC
workflow_dispatch:
env:
CMAKE_REQUIRED_QUIET: "OFF"
CTEST_OUTPUT_ON_FAILURE: "ON"
DEBIAN_FRONTEND: noninteractive
VERBOSE: 1
jobs:
job-by-hand-alpine-linux-gcc: # uses a POSIX-compliant shell
# ...and also uses a subdirectory "upx with space" in order to detect possible quoting issues
# ...and also uses ccache as we are running the same build-script again and again
if: github.repository_owner == 'upx'
strategy: { matrix: { container: ['alpine:3.9','alpine:3.18','alpine:edge','i386/alpine:edge'] } }
name: ${{ format('by-hand gcc {0}', matrix.container) }}
runs-on: ubuntu-latest
container: ${{ matrix.container }}
steps:
- name: ${{ format('Install packages {0}', matrix.container) }}
run: |
# install ccache, g++, git and various POSIX shells
shells="bash dash loksh mksh zsh"
case ${{ matrix.container }} in
*:3.18 | *:edge) shells="$shells oksh yash" ;;
esac
echo "installing shells: $shells"
apk update && apk upgrade && apk add ccache g++ git $shells
# enable ccache and some warnings
xflags="-static -Wall -Wextra -Werror"
echo -e "CC=ccache gcc $xflags\nCXX=ccache g++ -std=gnu++17 $xflags" >> $GITHUB_ENV
# this seems to be needed when running in a container (beause of UID mismatch??)
git config --global --add safe.directory '*'
# create user upx:upx 2000:2000 for file system tests below ("sudo")
adduser upx -u 2000 -D && cd /home/upx && chmod 00700 . && chown -R upx:upx .
- name: ${{ format('Check out UPX {0} source code', github.ref_name) }}
run: |
git clone --branch "$GITHUB_REF_NAME" --depth 1 https://github.com/upx/upx "upx with space"
git -C "upx with space" submodule update --init
- name: 'Build by-hand with /bin/sh'
run: '/bin/sh "./upx with space/misc/scripts/build_upx_by_hand.sh"'
- name: 'Build by-hand with bash'
run: 'bash "./upx with space/misc/scripts/build_upx_by_hand.sh"'
- name: 'Build by-hand with bash --posix'
run: 'bash --posix "./upx with space/misc/scripts/build_upx_by_hand.sh"'
- name: 'Build by-hand with busybox ash'
run: 'busybox ash "./upx with space/misc/scripts/build_upx_by_hand.sh"'
- name: 'Build by-hand with busybox sh'
run: 'busybox sh "./upx with space/misc/scripts/build_upx_by_hand.sh"'
- name: 'Build by-hand with dash'
run: 'dash "./upx with space/misc/scripts/build_upx_by_hand.sh"'
- name: 'Build by-hand with loksh'
run: 'ksh "./upx with space/misc/scripts/build_upx_by_hand.sh"'
- name: 'Build by-hand with loksh -o posix'
run: 'ksh -o posix "./upx with space/misc/scripts/build_upx_by_hand.sh"'
- name: 'Build by-hand with loksh -o sh'
run: 'ksh -o sh "./upx with space/misc/scripts/build_upx_by_hand.sh"'
- name: 'Build by-hand with mksh'
run: 'mksh "./upx with space/misc/scripts/build_upx_by_hand.sh"'
- name: 'Build by-hand with mksh -o posix'
run: 'mksh -o posix "./upx with space/misc/scripts/build_upx_by_hand.sh"'
- name: 'Build by-hand with mksh -o sh'
run: 'mksh -o sh "./upx with space/misc/scripts/build_upx_by_hand.sh"'
- name: 'Build by-hand with oksh'
if: endsWith(matrix.container, ':3.18') || endsWith(matrix.container, ':edge')
run: 'oksh "./upx with space/misc/scripts/build_upx_by_hand.sh"'
- name: 'Build by-hand with oksh -o posix'
if: endsWith(matrix.container, ':3.18') || endsWith(matrix.container, ':edge')
run: 'oksh -o posix "./upx with space/misc/scripts/build_upx_by_hand.sh"'
- name: 'Build by-hand with oksh -o sh'
if: endsWith(matrix.container, ':3.18') || endsWith(matrix.container, ':edge')
run: 'oksh -o sh "./upx with space/misc/scripts/build_upx_by_hand.sh"'
- name: 'Build by-hand with yash'
if: endsWith(matrix.container, ':3.18') || endsWith(matrix.container, ':edge')
run: 'yash "./upx with space/misc/scripts/build_upx_by_hand.sh"'
- name: 'Build by-hand with zsh'
run: 'zsh "./upx with space/misc/scripts/build_upx_by_hand.sh"'
- name: 'Build by-hand with zsh --emulate ksh'
run: 'zsh --emulate ksh "./upx with space/misc/scripts/build_upx_by_hand.sh"'
- name: 'Build by-hand with zsh --emulate sh'
run: 'zsh --emulate sh "./upx with space/misc/scripts/build_upx_by_hand.sh"'
- name: 'Show ccache stats'
run: |
ccache -s
ccache -p
- name: 'Run file system test suite (busybox)'
run: |
apk add bash sudo
testsuite="$(readlink -fn "upx with space"/misc/testsuite/test_symlinks.sh)"
cd "upx with space"/build/by-hand
# IMPORTANT: do NOT run as user root!
chmod a+w . && sudo -u upx bash "$testsuite"
- name: 'Run file system test suite (coreutils)'
run: |
apk add bash coreutils sudo
testsuite="$(readlink -fn "upx with space"/misc/testsuite/test_symlinks.sh)"
cd "upx with space"/build/by-hand
# IMPORTANT: do NOT run as user root!
chmod a+w . && sudo -u upx bash "$testsuite"
job-by-hand-macos: # uses a POSIX-compliant shell
# ...and also uses a subdirectory "upx with space" in order to detect possible quoting issues
if: github.repository_owner == 'upx'
strategy:
fail-fast: false
matrix:
include:
- { os: macos-11, run_fs_test: false } # macos-11 does not have "readlink -f"
- { os: macos-12, run_fs_test: true }
- { os: macos-13, run_fs_test: true }
name: ${{ format('by-hand cc {0}', matrix.os) }}
runs-on: ${{ matrix.os }}
steps:
- name: ${{ format('Check out UPX {0} source code', github.ref_name) }}
run: |
git clone --branch "$GITHUB_REF_NAME" --depth 1 https://github.com/upx/upx "upx with space"
git -C "upx with space" submodule update --init
- name: 'Build by-hand with /bin/sh'
run: 'top_srcdir="$PWD/upx with space" /bin/sh "./upx with space/misc/scripts/build_upx_by_hand.sh"'
- name: 'Build by-hand with bash'
run: 'top_srcdir="$PWD/upx with space" bash "./upx with space/misc/scripts/build_upx_by_hand.sh"'
- name: 'Run file system test suite'
if: ${{ matrix.run_fs_test }}
run: |
testsuite="$(readlink -fn "upx with space"/misc/testsuite/test_symlinks.sh)"
cd "upx with space"/build/by-hand
bash "$testsuite"
job-by-hand-windows-gcc: # uses a POSIX-compliant shell
# ...and also uses a subdirectory "upx with space" in order to detect possible quoting issues
if: github.repository_owner == 'upx'
strategy:
fail-fast: false
matrix:
include:
- { os: windows-2019 }
- { os: windows-2022 }
name: ${{ format('by-hand gcc {0}', matrix.os) }}
runs-on: ${{ matrix.os }}
steps:
- name: ${{ format('Check out UPX {0} source code', github.ref_name) }}
shell: bash
run: |
git clone --branch "$GITHUB_REF_NAME" --depth 1 https://github.com/upx/upx "upx with space"
git -C "upx with space" submodule update --init
- name: 'Build by-hand with bash'
shell: bash
run: |
xflags="-static -Wall -Wextra -Werror"
CC="gcc $xflags" CXX="g++ -std=gnu++17 $xflags" bash "./upx with space/misc/scripts/build_upx_by_hand.sh"
@@ -0,0 +1,56 @@
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
# BS BuildSystem: build on macOS with 'cmake -G Xcode'
name: 'Weekly CI BS - cmake macOS Xcode'
on:
schedule: [cron: '10 1 * * 3'] # run weekly Wednesday 01:10 UTC
workflow_dispatch:
env:
CMAKE_REQUIRED_QUIET: "OFF"
CTEST_OUTPUT_ON_FAILURE: "ON"
DEBIAN_FRONTEND: noninteractive
jobs:
job-cmake-macos-xcode: # uses cmake + xcodebuild
if: github.repository_owner == 'upx'
strategy:
fail-fast: false
matrix:
include:
- { os: macos-11, run_test: true }
- { os: macos-12, run_test: true }
- { os: macos-13, run_test: false } # TODO: enable once UPX fully works on macos-13
name: ${{ format('{0} cmake Xcode', matrix.os) }}
runs-on: ${{ matrix.os }}
steps:
- name: 'Check out code'
uses: actions/checkout@v4
with: { submodules: true }
- { name: 'Config cmake Xcode', run: 'cmake -S . -B build/xcode -G Xcode' }
- { name: 'Build cmake Xcode default', run: 'cmake --build build/xcode' }
- { name: 'Build cmake Xcode Debug', run: 'cmake --build build/xcode --config Debug' }
- { name: 'Build cmake Xcode Release', run: 'cmake --build build/xcode --config Release' }
- name: 'Make artifact'
run: |
N=$(echo "upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-weekly-ci-xcode-${{ matrix.os }}" | sed 's/[^0-9a-zA-Z_.-]/-/g')
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'
if: ${{ matrix.run_test }}
run: |
ctest --test-dir build/xcode -C Debug
# ctest --test-dir build/xcode -C Release
- name: 'Run install tests'
run: |
(cd build/xcode && DESTDIR=$PWD/Install-default cmake --install .)
(cd build/xcode && DESTDIR=$PWD/Install-debug cmake --install . --config Debug)
(cd build/xcode && DESTDIR=$PWD/Install-release cmake --install . --config Release)
ls -l build/xcode/Install-*/usr/local/bin/upx
@@ -0,0 +1,92 @@
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
# BS BuildSystem: build on Windows with 'cmake -G "Unix Makefiles"'
name: 'Weekly CI BS - cmake Windows make'
on:
schedule: [cron: '20 1 * * 3'] # run weekly Wednesday 01:20 UTC
workflow_dispatch:
env:
CMAKE_REQUIRED_QUIET: "OFF"
CTEST_OUTPUT_ON_FAILURE: "ON"
DEBIAN_FRONTEND: noninteractive
UPX_CMAKE_BUILD_FLAGS: --verbose
UPX_CMAKE_CONFIG_FLAGS: -G "Unix Makefiles"
jobs:
job-cmake-windows-make: # uses cmake + make
if: github.repository_owner == 'upx'
strategy:
fail-fast: false
matrix:
include:
# INFO: the following don't work with GNU make (probably some quoting problems with spaces or backslashes)
# => use Ninja generator instead; see weekly-ci-bs-cmake-windows-ninja.yml
# # cl (msvc)
# - { os: windows-2019, cc: cl, cxx: cl, vsversion: 2019, arch: amd64 }
# - { os: windows-2019, cc: cl, cxx: cl, vsversion: 2019, arch: amd64_arm64 }
# - { os: windows-2019, cc: cl, cxx: cl, vsversion: 2019, arch: amd64_x86 }
# - { os: windows-2022, cc: cl, cxx: cl, vsversion: 2022, arch: amd64 }
# - { os: windows-2022, cc: cl, cxx: cl, vsversion: 2022, arch: amd64_arm64 }
# - { os: windows-2022, cc: cl, cxx: cl, vsversion: 2022, arch: amd64_x86 }
# # clang-cl
# - { os: windows-2022, cc: clang-cl, cxx: clang-cl, vsversion: 2022, arch: amd64 }
# clang
- { os: windows-2022, cc: clang, cxx: 'clang++', arch: amd64, xflags: '-static' }
# gcc (mingw-gcc)
- { os: windows-2022, cc: gcc, cxx: 'g++', arch: amd64, xflags: '-static' }
env:
CC: ${{ matrix.cc }} ${{ matrix.xflags }}
CXX: ${{ matrix.cxx }} ${{ matrix.xflags }}
name: ${{ format('{0} {1} {2}', matrix.cc, matrix.vsversion, matrix.arch) }}
runs-on: ${{ matrix.os }}
steps:
- name: 'Check out code'
uses: actions/checkout@v4
with: { submodules: true }
- name: 'Set up Developer Command Prompt'
if: matrix.vsversion
uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1
with:
vsversion: ${{ matrix.vsversion }}
arch: ${{ matrix.arch }}
- name: 'Init environment'
shell: bash
run: |
xtarget="windows-make-${{ matrix.cc }}-${{ matrix.vsversion }}-${{ matrix.arch}}"
echo "xtarget=$xtarget" >> $GITHUB_ENV
- name: 'Build cmake Make Debug'
shell: bash
run: |
make UPX_XTARGET=$xtarget xtarget/debug
ls -l build/xtarget/$xtarget/debug/upx.exe
file build/xtarget/$xtarget/debug/upx.exe || true
- name: 'Build cmake Make Release'
shell: bash
run: |
make UPX_XTARGET=$xtarget xtarget/release
ls -l build/xtarget/$xtarget/release/upx.exe
file build/xtarget/$xtarget/release/upx.exe || true
- name: 'Make artifact'
shell: bash
run: |
N=$(echo "upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-weekly-ci-make-${xtarget}" | sed 's/[^0-9a-zA-Z_.-]/-/g')
mkdir -p "tmp/artifact/$N"
(cd build && cp -ai --parents xtarget/*/*/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'
if: ${{ matrix.arch != 'amd64_arm64' }}
shell: bash
run: |
ctest --test-dir build/xtarget/$xtarget/debug
ctest --test-dir build/xtarget/$xtarget/release
- name: 'Run install tests'
shell: bash
run: |
env DESTDIR=./Install-debug cmake --install build/xtarget/$xtarget/debug
env DESTDIR=./Install-release cmake --install build/xtarget/$xtarget/release
@@ -0,0 +1,91 @@
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
# BS BuildSystem: build on Windows with 'cmake -G Ninja'
name: 'Weekly CI BS - cmake Windows Ninja'
on:
schedule: [cron: '30 1 * * 3'] # run weekly Wednesday 01:30 UTC
workflow_dispatch:
env:
CMAKE_REQUIRED_QUIET: "OFF"
CTEST_OUTPUT_ON_FAILURE: "ON"
DEBIAN_FRONTEND: noninteractive
UPX_CMAKE_BUILD_FLAGS: --verbose
UPX_CMAKE_CONFIG_FLAGS: -G Ninja
jobs:
job-cmake-windows-ninja: # uses cmake + ninja
if: github.repository_owner == 'upx'
strategy:
fail-fast: false
matrix:
include:
# cl (msvc)
- { os: windows-2019, cc: cl, cxx: cl, vsversion: 2019, arch: amd64 }
- { os: windows-2019, cc: cl, cxx: cl, vsversion: 2019, arch: amd64_arm64 }
- { os: windows-2019, cc: cl, cxx: cl, vsversion: 2019, arch: amd64_x86 }
- { os: windows-2022, cc: cl, cxx: cl, vsversion: 2022, arch: amd64 }
- { os: windows-2022, cc: cl, cxx: cl, vsversion: 2022, arch: amd64_arm64 }
- { os: windows-2022, cc: cl, cxx: cl, vsversion: 2022, arch: amd64_x86 }
# clang-cl
- { os: windows-2022, cc: clang-cl, cxx: clang-cl, vsversion: 2022, arch: amd64 }
# clang
- { os: windows-2022, cc: clang, cxx: 'clang++', arch: amd64, xflags: '-static' }
# gcc (mingw-gcc)
- { os: windows-2022, cc: gcc, cxx: 'g++', arch: amd64, xflags: '-static' }
env:
CC: ${{ matrix.cc }} ${{ matrix.xflags }}
CXX: ${{ matrix.cxx }} ${{ matrix.xflags }}
name: ${{ format('{0} {1} {2}', matrix.cc, matrix.vsversion, matrix.arch) }}
runs-on: ${{ matrix.os }}
steps:
- name: 'Check out code'
uses: actions/checkout@v4
with: { submodules: true }
- name: 'Set up Developer Command Prompt'
if: matrix.vsversion
uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1
with:
vsversion: ${{ matrix.vsversion }}
arch: ${{ matrix.arch }}
- name: 'Init environment'
shell: bash
run: |
command -v ninja >/dev/null || choco install -y --no-progress ninja
xtarget="windows-ninja-${{ matrix.cc }}-${{ matrix.vsversion }}-${{ matrix.arch}}"
echo "xtarget=$xtarget" >> $GITHUB_ENV
- name: 'Build cmake Ninja Debug'
shell: bash
run: |
make UPX_XTARGET=$xtarget xtarget/debug
ls -l build/xtarget/$xtarget/debug/upx.exe
file build/xtarget/$xtarget/debug/upx.exe || true
- name: 'Build cmake Ninja Release'
shell: bash
run: |
make UPX_XTARGET=$xtarget xtarget/release
ls -l build/xtarget/$xtarget/release/upx.exe
file build/xtarget/$xtarget/release/upx.exe || true
- name: 'Make artifact'
shell: bash
run: |
N=$(echo "upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-weekly-ci-ninja-${xtarget}" | sed 's/[^0-9a-zA-Z_.-]/-/g')
mkdir -p "tmp/artifact/$N"
(cd build && cp -ai --parents xtarget/*/*/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'
if: ${{ matrix.arch != 'amd64_arm64' }}
shell: bash
run: |
ctest --test-dir build/xtarget/$xtarget/debug
ctest --test-dir build/xtarget/$xtarget/release
- name: 'Run install tests'
shell: bash
run: |
env DESTDIR=./Install-debug cmake --install build/xtarget/$xtarget/debug
env DESTDIR=./Install-release cmake --install build/xtarget/$xtarget/release
@@ -0,0 +1,78 @@
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
# BS BuildSystem: build on Windows with 'cmake -G "NMake Makefiles"'
name: 'Weekly CI BS - cmake Windows NMake'
on:
schedule: [cron: '40 1 * * 3'] # run weekly Wednesday 01:40 UTC
workflow_dispatch:
env:
CMAKE_REQUIRED_QUIET: "OFF"
CTEST_OUTPUT_ON_FAILURE: "ON"
DEBIAN_FRONTEND: noninteractive
jobs:
job-cmake-windows-nmake: # uses cmake + nmake
if: github.repository_owner == 'upx'
strategy:
fail-fast: false
matrix:
include:
# clang-cl
- { os: windows-2022, vsversion: 2022, arch: amd64, clang_cl: true }
# msvc
- { os: windows-2019, vsversion: 2019, arch: amd64 }
- { os: windows-2019, vsversion: 2019, arch: amd64_arm64 }
- { os: windows-2019, vsversion: 2019, arch: amd64_x86 }
- { os: windows-2022, vsversion: 2022, arch: amd64 }
- { os: windows-2022, vsversion: 2022, arch: amd64_arm64 }
- { os: windows-2022, vsversion: 2022, arch: amd64_x86 }
name: ${{ format('vs{0} {1} {2}', matrix.vsversion, matrix.arch, matrix.clang_cl && 'clang-cl' || '') }}
runs-on: ${{ matrix.os }}
steps:
- name: 'Check out code'
uses: actions/checkout@v4
with: { submodules: true }
- name: 'Set up Developer Command Prompt'
uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1
with:
vsversion: ${{ matrix.vsversion }}
arch: ${{ matrix.arch }}
- name: 'Build cmake NMake Debug'
shell: cmd
run: |
set X=${{ matrix.clang_cl && '-DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl' || '' }}
cmake -S . -B build/debug -G "NMake Makefiles" -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_BUILD_TYPE=Debug %X%
cd build/debug
nmake
dir *.exe
- name: 'Build cmake NMake Release'
shell: cmd
run: |
set X=${{ matrix.clang_cl && '-DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl' || '' }}
cmake -S . -B build/release -G "NMake Makefiles" -DCMAKE_VERBOSE_MAKEFILE=ON %X%
cd build/release
nmake
dir *.exe
- name: 'Make artifact'
shell: bash
run: |
X="${{ matrix.clang_cl && '-clang-cl' || '' }}"
N=$(echo "upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-weekly-ci-nmake-vs${{ matrix.vsversion }}-${{ matrix.arch }}$X" | sed 's/[^0-9a-zA-Z_.-]/-/g')
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'
if: ${{ matrix.arch != 'amd64_arm64' }}
run: |
ctest --test-dir build/debug
ctest --test-dir build/release
- name: 'Run install tests'
run: |
env DESTDIR=./Install-debug cmake --install build/debug
env DESTDIR=./Install-release cmake --install build/release
@@ -0,0 +1,204 @@
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
# CC CompilationCheck: test various clang and gcc versions
# Build under various Alpine Linux versions with clang and gcc, and
# also test building with C++20, C++23 and LTO.
# And also uses a subdirectory "upx with space" that contains whitespace in order
# to detect possible quoting issues.
# info: Alpine Linux 3.9 (released Jan 2019) has clang-5, cmake-3.13.0
# and gcc-8, which nicely matches our minimal build requirements
name: 'Weekly CI CC - Alpine Linux C++23'
on:
schedule: [cron: '00 2 * * 3'] # run weekly Wednesday 02:00 UTC
workflow_dispatch:
env:
CMAKE_REQUIRED_QUIET: "OFF"
CTEST_OUTPUT_ON_FAILURE: "ON"
DEBIAN_FRONTEND: noninteractive
UPX_CMAKE_CONFIG_FLAGS: -DCMAKE_VERBOSE_MAKEFILE=ON
UPX_TESTSUITE_LEVEL: 4
jobs:
job-alpine-cmake: # uses cmake + make
if: github.repository_owner == 'upx'
strategy:
fail-fast: false
matrix:
include:
- { container: 'alpine:3.9' , use_cxx20: 0, use_cxx2b: 0, use_lto: 0 } # Jan 2019: C++17; clang-5 & gcc-8
- { container: 'alpine:3.10', use_cxx20: 0, use_cxx2b: 0, use_lto: 0 }
- { container: 'alpine:3.11', use_cxx20: 0, use_cxx2b: 0, use_lto: 0 }
- { container: 'alpine:3.12', use_cxx20: 0, use_cxx2b: 0, use_lto: 0 }
- { container: 'alpine:3.13', use_cxx20: 1, use_cxx2b: 0, use_lto: 0 } # Jan 2021: C++20; clang-10 & gcc-10
- { container: 'alpine:3.14', use_cxx20: 1, use_cxx2b: 0, use_lto: 0 }
- { container: 'alpine:3.15', use_cxx20: 1, use_cxx2b: 0, use_lto: 1 } # Nov 2021: LTO; clang-12 & gcc-10 & binutils-2.37
- { container: 'alpine:3.16', use_cxx20: 1, use_cxx2b: 1, use_lto: 1 } # May 2022: C++2b; clang-13 & gcc-11
- { container: 'alpine:3.17', use_cxx20: 1, use_cxx2b: 1, use_lto: 1 }
- { container: 'alpine:3.18', use_cxx20: 1, use_cxx2b: 1, use_lto: 1 }
- { container: 'alpine:edge', use_cxx20: 1, use_cxx2b: 1, use_lto: 1 }
- { container: 'i386/alpine:edge', use_cxx20: 1, use_cxx2b: 1, use_lto: 1 }
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 clang cmake g++ git make
case ${{ matrix.container }} in
# clang-dev is needed on Alpine versions <= 3.11 for clang headers like <emmintrin.h>
*:3.[0-9] | *:3.1[0-1]) apk add clang-dev ;;
esac
case ${{ matrix.container }}-${{ matrix.use_lto }} in
# llvm-dev is needed on Alpine versions <= 3.18 for -flto
*:3.[0-9]-1 | *:3.1[0-8]-1) apk add llvm-dev ;;
esac
# set environment vars
x="$(apk list -I "$(apk info -Wq "$(which clang)")")"; echo "clang_package=${x%% *}" >> $GITHUB_ENV
x="$(apk list -I "$(apk info -Wq "$(which gcc)")")"; echo "gcc_package=${x%% *}" >> $GITHUB_ENV
N=$(echo "upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-weekly-ci-alpine-${{ matrix.container }}" | sed 's/[^0-9a-zA-Z_.-]/-/g')
echo "artifact_name=$N" >> $GITHUB_ENV
# create user upx:upx 2000:2000 for file system tests below ("sudo")
adduser upx -u 2000 -D && cd /home/upx && chmod 00700 . && chown -R upx:upx .
- name: ${{ format('Check out UPX {0} source code', github.ref_name) }}
run: |
git clone --branch "$GITHUB_REF_NAME" --depth 1 https://github.com/upx/upx "upx with space"
git -C "upx with space" submodule update --init
# build with default C11 and C++17
- name: ${{ format('Build clang Release with {0}', env.clang_package) }}
run: 'make -C "upx with space" UPX_XTARGET=clang-static CC="clang -static" CXX="clang++ -static"'
- name: ${{ format('Build clang Debug with {0}', env.clang_package) }}
run: 'make -C "upx with space" UPX_XTARGET=clang-static CC="clang -static" CXX="clang++ -static" xtarget/debug'
- name: ${{ format('Build gcc Release with {0}', env.gcc_package) }}
run: 'make -C "upx with space" UPX_XTARGET=gcc-static CC="gcc -static" CXX="g++ -static"'
- name: ${{ format('Build gcc Debug with {0}', env.gcc_package) }}
run: 'make -C "upx with space" UPX_XTARGET=gcc-static CC="gcc -static" CXX="g++ -static" xtarget/debug'
# build with C17 and C++20
- name: ${{ format('Build clang C++20 Release with {0}', env.clang_package) }}
if: matrix.use_cxx20
run: |
export UPX_CONFIG_DISABLE_C_STANDARD=ON UPX_CONFIG_DISABLE_CXX_STANDARD=ON
make -C "upx with space" UPX_XTARGET=clang-static-cxx20 CC="clang -static -std=gnu17" CXX="clang++ -static -std=gnu++20"
- name: ${{ format('Build clang C++20 Debug with {0}', env.clang_package) }}
if: matrix.use_cxx20
run: |
export UPX_CONFIG_DISABLE_C_STANDARD=ON UPX_CONFIG_DISABLE_CXX_STANDARD=ON
make -C "upx with space" UPX_XTARGET=clang-static-cxx20 CC="clang -static -std=gnu17" CXX="clang++ -static -std=gnu++20" xtarget/debug
- name: ${{ format('Build gcc C++20 Release with {0}', env.gcc_package) }}
if: matrix.use_cxx20
run: |
export UPX_CONFIG_DISABLE_C_STANDARD=ON UPX_CONFIG_DISABLE_CXX_STANDARD=ON
make -C "upx with space" UPX_XTARGET=gcc-static-cxx20 CC="gcc -static -std=gnu17" CXX="g++ -static -std=gnu++20"
- name: ${{ format('Build gcc C++20 Debug with {0}', env.gcc_package) }}
if: matrix.use_cxx20
run: |
export UPX_CONFIG_DISABLE_C_STANDARD=ON UPX_CONFIG_DISABLE_CXX_STANDARD=ON
make -C "upx with space" UPX_XTARGET=gcc-static-cxx20 CC="gcc -static -std=gnu17" CXX="g++ -static -std=gnu++20" xtarget/debug
# build with C23 and C++23
- name: ${{ format('Build clang C++23 Release with {0}', env.clang_package) }}
if: matrix.use_cxx23 || matrix.use_cxx2b
run: |
export UPX_CONFIG_DISABLE_C_STANDARD=ON UPX_CONFIG_DISABLE_CXX_STANDARD=ON
a=gnu23; b=gnu++23; if test "X${{ matrix.use_cxx2b }}" = X1; then a=gnu2x; b=gnu++2b; fi
make -C "upx with space" UPX_XTARGET=clang-static-cxx23 CC="clang -static -std=$a" CXX="clang++ -static -std=$b"
- name: ${{ format('Build clang C++23 Debug with {0}', env.clang_package) }}
if: matrix.use_cxx23 || matrix.use_cxx2b
run: |
export UPX_CONFIG_DISABLE_C_STANDARD=ON UPX_CONFIG_DISABLE_CXX_STANDARD=ON
a=gnu23; b=gnu++23; if test "X${{ matrix.use_cxx2b }}" = X1; then a=gnu2x; b=gnu++2b; fi
make -C "upx with space" UPX_XTARGET=clang-static-cxx23 CC="clang -static -std=$a" CXX="clang++ -static -std=$b" xtarget/debug
- name: ${{ format('Build gcc C++23 Release with {0}', env.gcc_package) }}
if: matrix.use_cxx23 || matrix.use_cxx2b
run: |
export UPX_CONFIG_DISABLE_C_STANDARD=ON UPX_CONFIG_DISABLE_CXX_STANDARD=ON
a=gnu23; b=gnu++23; if test "X${{ matrix.use_cxx2b }}" = X1; then a=gnu2x; b=gnu++2b; fi
make -C "upx with space" UPX_XTARGET=gcc-static-cxx23 CC="gcc -static -std=$a" CXX="g++ -static -std=$b"
- name: ${{ format('Build gcc C++23 Debug with {0}', env.gcc_package) }}
if: matrix.use_cxx23 || matrix.use_cxx2b
run: |
export UPX_CONFIG_DISABLE_C_STANDARD=ON UPX_CONFIG_DISABLE_CXX_STANDARD=ON
a=gnu23; b=gnu++23; if test "X${{ matrix.use_cxx2b }}" = X1; then a=gnu2x; b=gnu++2b; fi
make -C "upx with space" UPX_XTARGET=gcc-static-cxx23 CC="gcc -static -std=$a" CXX="g++ -static -std=$b" xtarget/debug
# build with -flto
- name: ${{ format('Build clang LTO Release with {0}', env.clang_package) }}
if: matrix.use_lto
run: |
make -C "upx with space" UPX_XTARGET=clang-static-cxxlto CC="clang -static -flto" CXX="clang++ -static -flto"
- name: ${{ format('Build clang LTO Debug with {0}', env.clang_package) }}
if: matrix.use_lto
run: |
make -C "upx with space" UPX_XTARGET=clang-static-cxxlto CC="clang -static -flto" CXX="clang++ -static -flto" xtarget/debug
- name: ${{ format('Build gcc LTO Release with {0}', env.gcc_package) }}
if: matrix.use_lto
run: |
make -C "upx with space" UPX_XTARGET=gcc-static-cxxlto CC="gcc -static -flto" CXX="g++ -static -flto"
- name: ${{ format('Build gcc LTO Debug with {0}', env.gcc_package) }}
if: matrix.use_lto
run: |
make -C "upx with space" UPX_XTARGET=gcc-static-cxxlto CC="gcc -static -flto" CXX="g++ -static -flto" xtarget/debug
- { name: 'Strip release binaries', run: 'strip -p --strip-unneeded "upx with space"/build/*/*/release/upx' }
- name: ${{ format('Upload artifact {0}', env.artifact_name) }}
if: ${{ !startsWith(matrix.container, 'i386/') }} # i386: missing nodejs on host
uses: actions/upload-artifact@v3
with:
name: ${{ env.artifact_name }}
path: 'upx with space*/build/*/*/*/upx'
- name: 'Run install tests'
run: |
(cd "upx with space"/build/xtarget/clang-static/debug && DESTDIR="$PWD/Install with cmake" cmake --install .)
(cd "upx with space"/build/xtarget/clang-static/debug && DESTDIR="$PWD/Install with make" make install)
(cd "upx with space"/build/xtarget/clang-static/release && DESTDIR="$PWD/Install with cmake" cmake --install .)
(cd "upx with space"/build/xtarget/clang-static/release && DESTDIR="$PWD/Install with make" make install)
(cd "upx with space"/build/xtarget/gcc-static/debug && DESTDIR="$PWD/Install with cmake" cmake --install .)
(cd "upx with space"/build/xtarget/gcc-static/debug && DESTDIR="$PWD/Install with make" make install)
(cd "upx with space"/build/xtarget/gcc-static/release && DESTDIR="$PWD/Install with cmake" cmake --install .)
(cd "upx with space"/build/xtarget/gcc-static/release && DESTDIR="$PWD/Install with make" make install)
- { name: 'Run basic tests clang Debug', run: 'make -C "upx with space"/build/xtarget/clang-static/debug test' }
- { name: 'Run basic tests clang Release', run: 'make -C "upx with space"/build/xtarget/clang-static/release test' }
- { name: 'Run basic tests gcc Debug', run: 'make -C "upx with space"/build/xtarget/gcc-static/debug test' }
- { name: 'Run basic tests gcc Release', run: 'make -C "upx with space"/build/xtarget/gcc-static/release test' }
- name: 'Run basic tests C++20, C++23 and LTO'
if: matrix.use_cxx20 || matrix.use_cxx23 || matrix.use_cxx2b || matrix.use_lto
run: |
for dir in "upx with space"/build/xtarget/*-cxx*/*; do
echo "===== $dir"
make -C "$dir" test
done
- name: 'Run file system test suite (busybox)'
run: |
apk add bash sudo
testsuite="$(readlink -fn "upx with space"/misc/testsuite/test_symlinks.sh)"
cd "upx with space"/build/xtarget/gcc-static/release
# IMPORTANT: do NOT run as user root!
chmod a+w . && sudo -u upx bash "$testsuite"
# test suite
- name: ${{ format('Run test suite level {0}', env.UPX_TESTSUITE_LEVEL) }}
run: |
# testsuite needs bash and working "readlink -en" and "sha256sum -b"
apk add bash coreutils
# use a directory that contains whitespace to detect possible quoting issues
git clone --depth=1 https://github.com/upx/upx-testsuite "upx-testsuite with space"
export upx_testsuite_SRCDIR="$(readlink -fn "upx-testsuite with space")"
testsuite_1="$(readlink -fn "upx with space"/misc/testsuite/upx_testsuite_1.sh)"
(cd "upx with space"/build/xtarget/gcc-static/release && upx_exe=./upx bash "$testsuite_1")
- name: 'Run file system test suite (coreutils)'
run: |
apk add bash coreutils sudo
testsuite="$(readlink -fn "upx with space"/misc/testsuite/test_symlinks.sh)"
cd "upx with space"/build/xtarget/gcc-static/release
# IMPORTANT: do NOT run as user root!
chmod a+w . && sudo -u upx bash "$testsuite"
@@ -0,0 +1,174 @@
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
# CC CompilationCheck: compile with various mingw-gcc versions and run tests under Wine
name: 'Weekly CI CC - Alpine Linux MinGW'
on:
schedule: [cron: '20 2 * * 3'] # run weekly Wednesday 02:20 UTC
workflow_dispatch:
env:
CMAKE_REQUIRED_QUIET: "OFF"
CTEST_OUTPUT_ON_FAILURE: "ON"
DEBIAN_FRONTEND: noninteractive
UPX_CMAKE_CONFIG_FLAGS: -DCMAKE_VERBOSE_MAKEFILE=ON
jobs:
job-alpine-mingw: # uses cmake + make
if: github.repository_owner == 'upx'
strategy:
fail-fast: false
matrix:
include:
- { container: 'alpine:3.11', wine: false, i686_mingw: false } # skip Wine testsuite; TODO: internal error: doctest check failed
- { container: 'alpine:3.12', wine: false, i686_mingw: false } # skip Wine testsuite; TODO: internal error: doctest check failed
- { container: 'alpine:3.13', wine: true, i686_mingw: false } # wine-4.0.3
- { container: 'alpine:3.14', wine: true, i686_mingw: false } # wine-6.18
- { container: 'alpine:3.15', wine: true, i686_mingw: false } # wine-6.23
- { container: 'alpine:3.16', wine: true, i686_mingw: false } # wine-7.8
- { container: 'alpine:3.17', wine: true, i686_mingw: false } # wine-7.21
# Wine >= 8.0 can run i686 32-bit programs in WOW64 mode on pure 64-bit systems
- { container: 'alpine:3.18', wine: true, i686_mingw: true } # wine-8.13
- { container: 'alpine:edge', wine: true, i686_mingw: true } # wine-8.17
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 cmake coreutils file git make tar xz
apk add mingw-w64-gcc
test "${{ matrix.i686_mingw }}" = "true" && apk add i686-mingw-w64-gcc
test "${{ matrix.wine }}" = "true" && apk add wine
true
- name: ${{ format('Check out UPX {0} source code', github.ref_name) }}
run: |
# this seems to be needed for Wine when running in a container (beause of UID mismatch??)
mkdir -p -v ~/.wine
# this seems to be needed when running in a container (beause of UID mismatch??)
git config --global --add safe.directory '*'
git clone --branch "$GITHUB_REF_NAME" --depth 1 https://github.com/upx/upx .
git submodule update --init
- name: 'Build cmake extra/cross-windows-mingw32/debug'
if: ${{ matrix.i686_mingw }}
run: 'make build/extra/cross-windows-mingw32/debug'
- name: 'Build cmake extra/cross-windows-mingw32/release'
if: ${{ matrix.i686_mingw }}
run: 'make build/extra/cross-windows-mingw32/release'
- name: 'Build cmake extra/cross-windows-mingw64/debug'
run: |
# on Alpine 3.11 and 3.12 CMake does not find AR; Alpine >= 3.13 (with CMake 3.18.4) works
X=
case ${{ matrix.container }} in
*:3.1[12]) X="CMAKE_AR=/usr/bin/x86_64-w64-mingw32-ar" ;;
esac
make build/extra/cross-windows-mingw64/debug $X
- name: 'Build cmake extra/cross-windows-mingw64/release'
run: |
# on Alpine 3.11 and 3.12 CMake does not find AR; Alpine >= 3.13 (with CMake 3.18.4) works
X=
case ${{ matrix.container }} in
*:3.1[12]) X="CMAKE_AR=/usr/bin/x86_64-w64-mingw32-ar" ;;
esac
make build/extra/cross-windows-mingw64/release $X
- name: 'Make artifact'
shell: bash
run: |
N=$(echo "upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-weekly-ci-alpine-mingw-${{ matrix.container }}" | sed 's/[^0-9a-zA-Z_.-]/-/g')
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: ${{ format('Run test suite under Wine') }}
if: ${{ matrix.wine }}
run: |
git clone --depth=1 https://github.com/upx/upx-testsuite ../upx-testsuite
testsuite_1="$(readlink -fn ./misc/testsuite/upx_testsuite_1.sh)"
export upx_exe_runner="wine64"
if test "${{ matrix.i686_mingw }}" = "true"; then
UPX_TESTSUITE_LEVEL=2 \
env -C build/extra/cross-windows-mingw32/debug upx_exe=./upx.exe bash "$testsuite_1"
UPX_TESTSUITE_LEVEL=4 \
env -C build/extra/cross-windows-mingw32/release upx_exe=./upx.exe bash "$testsuite_1"
fi
UPX_TESTSUITE_LEVEL=2 \
env -C build/extra/cross-windows-mingw64/debug upx_exe=./upx.exe bash "$testsuite_1"
UPX_TESTSUITE_LEVEL=4 \
env -C build/extra/cross-windows-mingw64/release upx_exe=./upx.exe bash "$testsuite_1"
- name: 'Run basic tests under Wine - mingw32/debug'
if: ${{ matrix.wine && matrix.i686_mingw }}
shell: bash
run: |
set -ex -o pipefail
cd build/extra/cross-windows-mingw32/debug
[[ -f upx && ! -f upx.exe ]] && mv -i -v upx upx.exe
pwd; file ./upx.exe
wine=wine64
tt='./upx.exe'
$wine ./upx.exe --version-short
$wine ./upx.exe -3 $tt -o tt.packed.exe
$wine ./upx.exe -l tt.packed.exe
$wine ./upx.exe -t tt.packed.exe
$wine ./upx.exe -d tt.packed.exe -o tt.unpacked.exe
$wine ./tt.packed.exe --version-short
$wine ./tt.unpacked.exe --version-short
- name: 'Run basic tests under Wine - mingw32/release'
if: ${{ matrix.wine && matrix.i686_mingw }}
shell: bash
run: |
set -ex -o pipefail
cd build/extra/cross-windows-mingw32/release
[[ -f upx && ! -f upx.exe ]] && mv -i -v upx upx.exe
pwd; file ./upx.exe
wine=wine64
tt='./upx.exe'
$wine ./upx.exe --version-short
$wine ./upx.exe -3 $tt -o tt.packed.exe
$wine ./upx.exe -l tt.packed.exe
$wine ./upx.exe -t tt.packed.exe
$wine ./upx.exe -d tt.packed.exe -o tt.unpacked.exe
$wine ./tt.packed.exe --version-short
$wine ./tt.unpacked.exe --version-short
- name: 'Run basic tests under Wine - mingw64/debug'
if: ${{ matrix.wine }}
shell: bash
run: |
set -ex -o pipefail
cd build/extra/cross-windows-mingw64/debug
[[ -f upx && ! -f upx.exe ]] && mv -i -v upx upx.exe
pwd; file ./upx.exe
wine=wine64
tt='./upx.exe'
$wine ./upx.exe --version-short
$wine ./upx.exe -3 $tt -o tt.packed.exe
$wine ./upx.exe -l tt.packed.exe
$wine ./upx.exe -t tt.packed.exe
$wine ./upx.exe -d tt.packed.exe -o tt.unpacked.exe
$wine ./tt.packed.exe --version-short
$wine ./tt.unpacked.exe --version-short
- name: 'Run basic tests under Wine - mingw64/release'
if: ${{ matrix.wine }}
shell: bash
run: |
set -ex -o pipefail
cd build/extra/cross-windows-mingw64/release
[[ -f upx && ! -f upx.exe ]] && mv -i -v upx upx.exe
pwd; file ./upx.exe
wine=wine64
tt='./upx.exe'
$wine ./upx.exe --version-short
$wine ./upx.exe -3 $tt -o tt.packed.exe
$wine ./upx.exe -l tt.packed.exe
$wine ./upx.exe -t tt.packed.exe
$wine ./upx.exe -d tt.packed.exe -o tt.unpacked.exe
$wine ./tt.packed.exe --version-short
$wine ./tt.unpacked.exe --version-short
@@ -0,0 +1,78 @@
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
# CC CompilationCheck: test llvm-mingw
# see https://github.com/mstorsjo/llvm-mingw
name: 'Weekly CI CC - llvm-mingw'
on:
schedule: [cron: '30 2 * * 3'] # run weekly Wednesday 02:30 UTC
workflow_dispatch:
env:
CMAKE_REQUIRED_QUIET: "OFF"
CTEST_OUTPUT_ON_FAILURE: "ON"
DEBIAN_FRONTEND: noninteractive
jobs:
job-llvm-mingw: # uses cmake + make
if: github.repository_owner == 'upx'
strategy:
fail-fast: false
matrix:
include:
- name: llvm-mingw-20230614-msvcrt
llvm_version: 16.0.6
url: 'https://github.com/mstorsjo/llvm-mingw/releases/download/20230614/llvm-mingw-20230614-msvcrt-ubuntu-20.04-x86_64.tar.xz'
- name: llvm-mingw-20230614-ucrt
llvm_version: 16.0.6
url: 'https://github.com/mstorsjo/llvm-mingw/releases/download/20230614/llvm-mingw-20230614-ucrt-ubuntu-20.04-x86_64.tar.xz'
- name: llvm-mingw-20231017-msvcrt
llvm_version: 17.0.3
url: 'https://github.com/mstorsjo/llvm-mingw/releases/download/20231017/llvm-mingw-20231017-msvcrt-ubuntu-20.04-x86_64.tar.xz'
- name: llvm-mingw-20231017-ucrt
llvm_version: 17.0.3
url: 'https://github.com/mstorsjo/llvm-mingw/releases/download/20231017/llvm-mingw-20231017-ucrt-ubuntu-20.04-x86_64.tar.xz'
name: ${{ format('{0} {1}', matrix.name, matrix.llvm_version) }}
runs-on: ubuntu-latest
steps:
- name: 'Check out code'
uses: actions/checkout@v4
with: { submodules: true }
- name: ${{ format('Install {0} {1}', matrix.name, matrix.llvm_version) }}
run: |
mkdir -p -v ~/.local/bin
cd ~/.local/bin
wget -q '${{ matrix.url }}'
ls -l ./llvm-mingw*.tar.*
tar -xoaf ./llvm-mingw*.tar.*
rm ./llvm-mingw*.tar.*
# update PATH
cd ./llvm-mingw*/bin
echo "PATH=$PWD:$PATH" >> $GITHUB_ENV
- name: 'Build clang aarch64'
run: |
export CC="aarch64-w64-mingw32-clang -static" CXX="aarch64-w64-mingw32-clang++ -static"
make UPX_XTARGET=aarch64-w64-mingw32-clang xtarget/debug xtarget/release
- name: 'Build clang armv7'
run: |
export CC="armv7-w64-mingw32-clang -static" CXX="armv7-w64-mingw32-clang++ -static"
make UPX_XTARGET=armv7-w64-mingw32-clang xtarget/debug xtarget/release
- name: 'Build clang i686'
run: |
export CC="i686-w64-mingw32-clang -static" CXX="i686-w64-mingw32-clang++ -static"
make UPX_XTARGET=i686-w64-mingw32-clang xtarget/debug xtarget/release
- name: 'Build clang x86_64'
run: |
export CC="x86_64-w64-mingw32-clang -static" CXX="x86_64-w64-mingw32-clang++ -static"
make UPX_XTARGET=x86_64-w64-mingw32-clang xtarget/debug xtarget/release
- name: 'Make artifact'
run: |
N=$(echo "upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-weekly-ci-${{ matrix.name }}-${{ matrix.llvm_version }}" | sed 's/[^0-9a-zA-Z_.-]/-/g')
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
+129
View File
@@ -0,0 +1,129 @@
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
# CC CompilationCheck: test zigcc
# build with "zig cc"; see https://ziglang.org/download/
name: 'Weekly CI CC - zigcc'
on:
schedule: [cron: '40 2 * * 3'] # run weekly Wednesday 02:40 UTC
workflow_dispatch:
env:
CMAKE_REQUIRED_QUIET: "OFF"
CTEST_OUTPUT_ON_FAILURE: "ON"
DEBIAN_FRONTEND: noninteractive
# 2023-10-24
ZIG_DIST_VERSION: 0.12.0-dev.1245+a07f288eb
jobs:
job-linux-zigcc: # uses cmake + make
if: github.repository_owner == 'upx'
strategy:
fail-fast: false
matrix:
include:
- { zig_target: aarch64-linux-musl }
- { zig_target: aarch64-linux-musl, zig_pic: -fPIE }
- { zig_target: aarch64-macos-none }
- { zig_target: aarch64-macos.11.0-none }
- { zig_target: aarch64-macos.12.0-none }
- { zig_target: aarch64-macos.13.0-none }
- { zig_target: aarch64-windows-gnu }
- { zig_target: arm-linux-musleabihf }
- { zig_target: arm-linux-musleabihf, zig_pic: -fPIE }
- { zig_target: i386-linux-musl }
- { zig_target: i386-linux-musl, zig_pic: -fPIE }
- { zig_target: i386-windows-gnu }
- { zig_target: mips-linux-musl }
- { zig_target: mipsel-linux-musl }
- { zig_target: powerpc-linux-musl }
- { zig_target: powerpc64-linux-musl }
- { zig_target: powerpc64le-linux-musl }
- { zig_target: x86_64-linux-musl }
- { zig_target: x86_64-linux-musl, zig_pic: -fPIE }
- { zig_target: x86_64-macos-none }
- { zig_target: x86_64-macos.11.0-none }
- { zig_target: x86_64-macos.12.0-none }
- { zig_target: x86_64-macos.13.0-none }
- { zig_target: x86_64-windows-gnu }
name: ${{ format('zigcc {0} {1}', matrix.zig_target, matrix.zig_pic) }}
runs-on: ubuntu-latest
container: 'alpine:3.18' # older versions such as alpine:3.12 also work; no-container also works
env:
# 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@v4
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=$(echo "upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-weekly-ci-zigcc-${{ matrix.zig_target }}${ZIG_PIC}" | sed 's/[^0-9a-zA-Z_.-]/-/g')
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 install tests'
if: ${{ contains(matrix.zig_target, '-linux') }}
run: |
(cd build/zig/${ZIG_TARGET}${ZIG_PIC}/release && DESTDIR=$PWD/Install-with-cmake cmake --install .)
(cd build/zig/${ZIG_TARGET}${ZIG_PIC}/release && DESTDIR=$PWD/Install-with-make make install)
+116
View File
@@ -0,0 +1,116 @@
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
# RT RunTime checks
# runs ASAN, MSAN, qemu and valgrind checkers; slow!
name: 'Weekly CI RT - ASAN MSAN Valgrind'
on:
schedule: [cron: '00 3 * * 3'] # run weekly Wednesday 03:00 UTC
workflow_dispatch:
env:
CMAKE_REQUIRED_QUIET: "OFF"
CTEST_OUTPUT_ON_FAILURE: "ON"
DEBIAN_FRONTEND: noninteractive
jobs:
job-runtime-checkers: # uses cmake + make
if: github.repository_owner == 'upx'
strategy:
fail-fast: false
matrix:
include:
- container: 'alpine:3.18'
release: debug
qemu: 'qemu-x86_64 -cpu Westmere'
- container: 'alpine:3.18'
release: release
qemu: 'qemu-x86_64 -cpu Westmere'
- container: 'alpine:edge'
release: release
qemu: 'qemu-x86_64 -cpu Westmere'
- container: 'i386/alpine:edge'
release: release
qemu: 'qemu-i386'
name: ${{ format('{0} {1}', matrix.container, matrix.release) }}
runs-on: ubuntu-latest
container: ${{ matrix.container }}
env:
release: ${{ matrix.release }}
steps:
- name: ${{ format('Install packages {0} {1}', matrix.container, matrix.release) }}
run: |
apk update && apk upgrade
apk add bash clang cmake compiler-rt coreutils g++ git make qemu-i386 qemu-x86_64 tar valgrind
# this seems to be needed when running in a container (beause of UID mismatch??)
git config --global --add safe.directory '*'
- name: ${{ format('Check out UPX {0} source code', github.ref_name) }}
run: |
git clone --branch "$GITHUB_REF_NAME" --depth 1 https://github.com/upx/upx .
git submodule update --init
git clone --depth=1 https://github.com/upx/upx-testsuite ../upx-testsuite
- name: 'Build clang-static'
run: |
export CC="clang -static" CXX="clang++ -static"
make UPX_XTARGET=clang-static xtarget/$release
- name: 'Build clang-asan'
if: ${{ !startsWith(matrix.container, 'i386/') }} # i386: ASAN not supported
run: |
# unfortunately ASAN does not support static linking
flags="-fsanitize=address -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize=undefined -fno-omit-frame-pointer"
export CC="clang $flags" CXX="clang++ $flags"
make UPX_XTARGET=clang-asan xtarget/$release
- name: 'Build clang-msan'
if: ${{ !startsWith(matrix.container, 'i386/') }} # i386: MSAN not supported
run: |
# unfortunately MSAN does not support static linking
flags="-fsanitize=memory -fsanitize=undefined -fno-omit-frame-pointer -DDOCTEST_CONFIG_DISABLE=1"
export CC="clang $flags" CXX="clang++ $flags"
make UPX_XTARGET=clang-msan xtarget/$release
- name: 'Make artifact'
run: |
N=$(echo "upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-weekly-ci-runtime-checkers-${{ matrix.container }}-${{ matrix.release }}" | sed 's/[^0-9a-zA-Z_.-]/-/g')
mkdir -p "tmp/artifact/$N"
(cd build && cp -ai --parents */*/*/upx "../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) }}
if: ${{ !startsWith(matrix.container, 'i386/') }} # i386: missing nodejs on host
uses: actions/upload-artifact@v3
with:
name: ${{ env.artifact_name }}
path: tmp/artifact
- name: 'Run basic tests clang-static'
run: 'make -C build/xtarget/clang-static/$release test'
- name: 'Run basic tests clang-asan'
if: ${{ !startsWith(matrix.container, 'i386/') }} # i386: ASAN not supported
run: 'make -C build/xtarget/clang-asan/$release test'
- name: 'Run basic tests clang-msan'
if: ${{ !startsWith(matrix.container, 'i386/') }} # i386: MSAN not supported
run: 'make -C build/xtarget/clang-msan/$release test'
- name: 'Run testsuite clang-asan'
if: ${{ !startsWith(matrix.container, 'i386/') }} # i386: ASAN not supported
run: |
export ASAN_OPTIONS="detect_invalid_pointer_pairs=2"
env -C build/xtarget/clang-asan/$release "$PWD"/misc/testsuite/upx_testsuite_1.sh
- name: 'Run testsuite clang-msan'
if: ${{ !startsWith(matrix.container, 'i386/') }} # i386: MSAN not supported
run: |
env -C build/xtarget/clang-msan/$release "$PWD"/misc/testsuite/upx_testsuite_1.sh
- name: 'Run testsuite clang-static - QEMU'
if: ${{ matrix.qemu }}
run: |
export upx_exe_runner="${{ matrix.qemu }}"
env -C build/xtarget/clang-static/$release "$PWD"/misc/testsuite/upx_testsuite_1.sh
- name: 'Run testsuite clang-static - Valgrind'
if: true # very slow
run: |
export upx_exe_runner="valgrind --error-exitcode=1 --quiet"
# on current GitHub CI, takes about 30 minutes for release and 80 minutes for debug builds
# reduce time for debug builds to about 30 minutes
test "$release" = "debug" && export UPX_TESTSUITE_LEVEL=4
env -C build/xtarget/clang-static/$release "$PWD"/misc/testsuite/upx_testsuite_1.sh
+14 -2
View File
@@ -1,28 +1,40 @@
/.hg*
/.vscode*
/Makevars.global*
/Testing*
/build*
/maint*
/vendor*
GNUmakefile
MMakefile
GNUmakefile*
MMakefile*
Makevars.local*
compile_flags*.txt
Tmp*
tmp*
*.a
*.bz2
*.d
*.dll
*.dylib
*.exe
*.gz
*.lib
*.map
*.o
*.obj
*.out
*.patch
*.py[cdo]
*.rar
*.so
*.swp
*.tmp
*.ttp
*.xz
*.zip
*.zst
doc/*.man
doc/*.ps
+400 -141
View File
@@ -1,21 +1,37 @@
cmake_minimum_required(VERSION 3.8.0 FATAL_ERROR)
#
# UPX "CMake" build file; see https://cmake.org/
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
#
# Build requirements:
# A C++ compiler that fully implements 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)
# CMake version check; using a somewhat current CMake version is highly recommended
if(DEFINED UPX_CONFIG_CMAKE_MINIMUM_REQUIRED_VERSION)
cmake_minimum_required(VERSION "${UPX_CONFIG_CMAKE_MINIMUM_REQUIRED_VERSION}" FATAL_ERROR)
else()
cmake_minimum_required(VERSION 3.8 FATAL_ERROR) # CMake >= 3.8 is needed for CXX_STANDARD 17
endif()
# 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_WSTRICT "Do not compile with strict compiler warnings." ON)
option(UPX_CONFIG_DISABLE_WERROR "Do not compile with default -Werror option." ON)
else()
# strict config defaults for devel builds
# strict config defaults for Git developer 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_WSTRICT "Do not compile with strict compiler warnings." 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!
# IMPORTANT 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)
#***********************************************************************
@@ -24,48 +40,88 @@ option(UPX_CONFIG_DISABLE_SELF_PACK_TEST "Do not test packing UPX with itself" O
# 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)
if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git")
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
# useful for CI jobs: allow settings via environment and cache result
function(upx_cache_bool_vars)
set(default_value "${ARGV0}")
list(REMOVE_AT ARGV 0)
foreach(var ${ARGV})
set(value ${default_value})
if(DEFINED UPX_CACHE_${var}) # cached
set(value "${UPX_CACHE_${var}}")
elseif(DEFINED ${var}) # defined via "cmake -DXXX=YYY"
set(value "${${var}}")
elseif("$ENV{${var}}" MATCHES "^(0|1|OFF|ON|FALSE|TRUE)$") # environment
set(value "$ENV{${var}}")
set(UPX_CACHE_ORIGIN_FROM_ENV_${var} TRUE CACHE INTERNAL "" FORCE)
endif()
if(value)
set(value ON)
else()
set(value OFF)
endif()
if(UPX_CACHE_ORIGIN_FROM_ENV_${var})
message(STATUS "setting from environment: ${var} = ${value}")
endif()
set(${var} "${value}" PARENT_SCOPE)
set(UPX_CACHE_${var} "${value}" CACHE INTERNAL "" FORCE)
endforeach()
endfunction()
# global settings
if(${CMAKE_VERSION} VERSION_GREATER "3.14.7" AND NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded")
cmake_policy(SET CMP0091 NEW)
endif()
# global CMake settings that default to ON
upx_cache_bool_vars(ON
CMAKE_C_STANDARD_REQUIRED CMAKE_CXX_STANDARD_REQUIRED
CMAKE_EXPORT_COMPILE_COMMANDS CMAKE_REQUIRED_QUIET
)
# internal UPX settings that default to OFF
upx_cache_bool_vars(OFF
UPX_CONFIG_CMAKE_DISABLE_TEST UPX_CONFIG_CMAKE_DISABLE_INSTALL
UPX_CONFIG_CMAKE_DISABLE_PRINT_INFO UPX_CONFIG_CMAKE_DISABLE_PLATFORM_CHECK
UPX_CONFIG_DISABLE_C_STANDARD UPX_CONFIG_DISABLE_CXX_STANDARD
)
# 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 "+")
if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git" AND NOT UPX_CONFIG_DISABLE_GITREV)
find_package(Git)
if(Git_FOUND)
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()
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}\"")
@@ -78,153 +134,328 @@ 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"
# set the default build type to "Release"
get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(NOT is_multi_config AND NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE)
endif()
# CMake init
project(upx VERSION 4.2.0 LANGUAGES C CXX)
# set the default multi-config build type to "Release"
if(is_multi_config)
set(c "${CMAKE_CONFIGURATION_TYPES}")
list(INSERT c 0 "Release")
list(INSERT c 1 "Debug")
if (CMAKE_BUILD_TYPE)
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()
# set MSVC_FRONTEND and MINGW
if(NOT DEFINED MSVC_FRONTEND AND (MSVC OR CMAKE_C_COMPILER_FRONTEND_VARIANT MATCHES "^MSVC"))
set(MSVC_FRONTEND 1)
endif()
if(NOT DEFINED MINGW AND CMAKE_C_PLATFORM_ID MATCHES "^MinGW")
set(MINGW 1)
endif()
#***********************************************************************
# targets and compilation flags
# common 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
include(CheckCCompilerFlag)
include(CheckFunctionExists)
include(CheckIncludeFile)
include(CheckStructHasMember)
include(CheckSymbolExists)
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)
if(NOT DEFINED HAVE_UNISTD_H)
check_include_file("unistd.h" HAVE_UNISTD_H)
endif()
if(NOT DEFINED HAVE_UTIMENSAT)
check_function_exists(utimensat HAVE_UTIMENSAT_FUNCTION__)
if(HAVE_UTIMENSAT_FUNCTION__)
check_symbol_exists(utimensat "sys/types.h;fcntl.h;sys/stat.h" HAVE_UTIMENSAT_SYMBOL__)
if(HAVE_UTIMENSAT_SYMBOL__)
CHECK_STRUCT_HAS_MEMBER("struct stat" "st_mtim.tv_nsec" "sys/types.h;fcntl.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
if(NOT HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
CHECK_STRUCT_HAS_MEMBER("struct stat" "st_mtimespec.tv_nsec" "sys/types.h;fcntl.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
endif()
if(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC OR HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
set(HAVE_UTIMENSAT 1)
endif()
endif()
endif()
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
)
if(UPX_CONFIG_DISABLE_WSTRICT)
# enable all basic warnings
set(warn_Wall -Wall)
set(warn_WN -W3)
else()
# enable all basic warnings, and enable lots of strict warnings
set(warn_Wall -Wall -Wextra -Wcast-align -Wcast-qual -Wmissing-declarations -Wpointer-arith -Wshadow -Wvla -Wwrite-strings)
set(warn_WN -W4)
endif()
if(UPX_CONFIG_DISABLE_WERROR)
# warnings are just warnings
set(warn_Werror "")
set(warn_WX "")
else()
# warnings are fatal errors; annoy developers to keep the source code warning-free
set(warn_Werror -Werror)
set(warn_WX -WX)
endif()
if(MSVC_FRONTEND)
# disable warning C5105 which may get triggered by some older versions of <windows.h>
set(warn_WX -wd5105 ${warn_WX})
endif()
if(NOT MSVC)
function(upx_add_definitions_with_prefix)
set(flag_prefix "${ARGV0}")
if(flag_prefix MATCHES "^empty$") # need "empty" to work around bug in old CMake versions
set(flag_prefix "")
endif()
list(REMOVE_AT ARGV 0)
set(failed "")
foreach(f ${ARGV})
set(flag "${flag_prefix}${f}")
string(REGEX REPLACE "[^0-9a-zA-Z_]" "_" cache_var "HAVE_CFLAG_${flag}")
check_c_compiler_flag("${flag}" ${cache_var})
if(${cache_var})
#message(STATUS "add_definitions: ${flag}")
add_definitions("${flag}")
else()
list(APPEND failed "${f}")
endif()
endforeach()
set(failed_flags "${failed}" PARENT_SCOPE) # return value
endfunction()
function(upx_add_definitions)
set(failed_flags "")
if(MSVC_FRONTEND AND CMAKE_C_COMPILER_ID MATCHES "Clang")
# for clang-cl try "-clang:" flag prefix first
upx_add_definitions_with_prefix("-clang:" ${ARGV})
upx_add_definitions_with_prefix("empty" ${failed_flags})
else()
upx_add_definitions_with_prefix("empty" ${ARGV})
endif()
endfunction()
if(NOT CMAKE_C_COMPILER_ID MATCHES "^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)
if(MSVC_FRONTEND OR WIN32 OR MINGW OR CYGWIN)
# 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)
add_definitions(-DWIN32_LEAN_AND_MEAN)
endif()
if(MSVC_FRONTEND)
# use -funsigned-char; set __cplusplus according to selected C++ standard
add_definitions(-J -Zc:__cplusplus)
if(CMAKE_C_COMPILER_ID MATCHES "^MSVC")
upx_add_definitions(-Zc:preprocessor) # use new preprocessor
endif()
add_definitions(-fno-strict-aliasing -fno-strict-overflow -funsigned-char)
endif()
if(NOT CMAKE_C_COMPILER_ID MATCHES "^MSVC")
# protect against security threats caused by misguided compiler "optimizations"
upx_add_definitions(-fno-delete-null-pointer-checks -fno-lifetime-dse)
upx_add_definitions(-fno-strict-aliasing -fno-strict-overflow -funsigned-char)
# disable overambitious auto-vectorization until this actually gains something
add_definitions(-fno-tree-vectorize)
upx_add_definitions(-fno-tree-vectorize)
# disable annoying clang warnings which get added by the macOS Xcode cmake generator
if(CMAKE_GENERATOR MATCHES "Xcode")
upx_add_definitions(-Wno-shorten-64-to-32)
endif()
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>)
# compile a source file with -O2 even in Debug build
function(upx_compile_source_debug_with_O2)
set(flags "$<$<CONFIG:Debug>:-O2>")
if (CMAKE_VERSION VERSION_LESS 3.8)
# 3.8: The COMPILE_FLAGS source file property learned to support generator expressions
if (is_multi_config OR NOT CMAKE_BUILD_TYPE MATCHES "^Debug$")
return()
endif()
set(flags "-O2")
endif()
if(CMAKE_GENERATOR MATCHES "Xcode") # multi-config
# NOTE: Xcode does not support per-config per-source COMPILE_FLAGS (as of CMake 3.27.7)
return()
endif()
foreach(t ${ARGV})
if(MSVC_FRONTEND)
# MSVC uses some Debug compilation options like -RTC1 that are incompatible with -O2
else()
get_source_file_property(prop ${t} COMPILE_FLAGS)
if(prop MATCHES "^(NOTFOUND)?$")
set_source_files_properties(${t} PROPERTIES COMPILE_FLAGS "${flags}")
else()
set_source_files_properties(${t} PROPERTIES COMPILE_FLAGS "${prop} ${flags}")
endif()
endif()
endforeach()
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)
# compile a target with -O2 even in Debug build
function(upx_compile_target_debug_with_O2)
foreach(t ${ARGV})
if(MSVC_FRONTEND)
# MSVC uses some Debug compilation options like -RTC1 that are incompatible with -O2
else()
target_compile_options(${t} PRIVATE $<$<CONFIG:Debug>:-O2>)
endif()
endforeach()
endfunction()
# sanitize a target
function(upx_sanitize_target)
foreach(t ${ARGV})
if(UPX_CONFIG_DISABLE_SANITIZE)
# no-op
elseif(MSVC_FRONTEND)
# MSVC uses -GS (similar to -fstack-protector) by default
elseif(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:MinSizeRel>:-fstack-protector>)
target_compile_options(${t} PRIVATE $<$<CONFIG:Release>:-fstack-protector>)
target_compile_options(${t} PRIVATE $<$<CONFIG:RelWithDebInfo>:-fstack-protector>)
endif()
endif()
endforeach()
endfunction()
#***********************************************************************
# targets
#***********************************************************************
# internal settings; these may change in a future versions
set(UPX_CONFIG_DISABLE_THREADS ON) # multithreading is currently not used; maybe in UPX version 5
set(UPX_CONFIG_DISABLE_BZIP2 ON) # bzip2 is currently not used; we might need it to decompress linux kernels
set(UPX_CONFIG_DISABLE_ZSTD ON) # zstd is currently not used; maybe in UPX version 5
if(NOT UPX_CONFIG_DISABLE_THREADS)
find_package(Threads)
endif()
if(NOT UPX_CONFIG_DISABLE_BZIP2)
file(GLOB bzip2_SOURCES "vendor/bzip2/*.c")
list(SORT bzip2_SOURCES)
add_library(upx_vendor_bzip2 STATIC ${bzip2_SOURCES})
if(NOT UPX_CONFIG_DISABLE_C_STANDARD)
set_property(TARGET upx_vendor_bzip2 PROPERTY C_STANDARD 11)
endif()
endif() # UPX_CONFIG_DISABLE_BZIP2
file(GLOB ucl_SOURCES "vendor/ucl/src/*.c")
list(SORT ucl_SOURCES)
add_library(upx_vendor_ucl STATIC ${ucl_SOURCES})
if(NOT UPX_CONFIG_DISABLE_C_STANDARD)
set_property(TARGET upx_vendor_ucl PROPERTY C_STANDARD 11)
endif()
file(GLOB zlib_SOURCES "vendor/zlib/*.c")
list(SORT zlib_SOURCES)
add_library(upx_vendor_zlib STATIC ${zlib_SOURCES})
if(NOT UPX_CONFIG_DISABLE_C_STANDARD)
set_property(TARGET upx_vendor_zlib PROPERTY C_STANDARD 11)
endif()
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})
if(NOT UPX_CONFIG_DISABLE_C_STANDARD)
set_property(TARGET upx_vendor_zstd PROPERTY C_STANDARD 11)
endif()
endif() # UPX_CONFIG_DISABLE_ZSTD
file(GLOB upx_SOURCES "src/*.cpp" "src/[cfu]*/*.cpp")
list(SORT upx_SOURCES)
add_executable(upx ${upx_SOURCES})
if(NOT UPX_CONFIG_DISABLE_CXX_STANDARD)
set_property(TARGET upx PROPERTY CXX_STANDARD 17)
endif()
target_link_libraries(upx upx_vendor_ucl upx_vendor_zlib)
if(NOT UPX_CONFIG_DISABLE_BZIP2)
target_link_libraries(upx upx_vendor_bzip2)
endif()
if(NOT UPX_CONFIG_DISABLE_ZSTD)
target_link_libraries(upx upx_vendor_zstd)
endif()
if(Threads_FOUND)
target_link_libraries(upx Threads::Threads)
endif()
#***********************************************************************
# target compilation flags
#***********************************************************************
if(NOT UPX_CONFIG_DISABLE_BZIP2)
set(t upx_vendor_bzip2)
upx_compile_target_debug_with_O2(${t})
upx_sanitize_target(${t})
if(MSVC_FRONTEND)
target_compile_options(${t} PRIVATE ${warn_WN} -wd4127 -wd4244 -wd4267 ${warn_WX})
else()
target_compile_options(${t} PRIVATE ${warn_Wall} -Wno-implicit-fallthrough ${warn_Werror})
endif()
endif() # UPX_CONFIG_DISABLE_BZIP2
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})
if(MSVC_FRONTEND)
target_compile_options(${t} PRIVATE ${warn_WN} ${warn_WX})
else()
target_compile_options(${t} PRIVATE ${warn_strict} ${warn_Werror})
target_compile_options(${t} PRIVATE ${warn_Wall} ${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})
target_compile_definitions(${t} PRIVATE HAVE_VSNPRINTF=1)
if(HAVE_UNISTD_H)
target_compile_definitions(${t} PRIVATE HAVE_UNISTD_H=1)
endif()
if(MSVC_FRONTEND)
target_compile_options(${t} PRIVATE -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})
target_compile_options(${t} PRIVATE -Wall ${warn_Werror})
##target_compile_options(${t} PRIVATE ${warn_Wall} -Wno-cast-align -Wno-cast-qual ${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})
target_compile_definitions(${t} PRIVATE DYNAMIC_BMI2=0 ZSTD_DISABLE_ASM=1)
if(MSVC_FRONTEND)
target_compile_options(${t} PRIVATE ${warn_WN} ${warn_WX})
else()
target_compile_options(${t} PRIVATE ${warn_strict} ${warn_Werror})
endif()
target_compile_options(${t} PRIVATE ${warn_Wall} ${warn_Werror})
endif()
endif() # UPX_CONFIG_DISABLE_ZSTD
set(t upx)
target_include_directories(${t} PRIVATE vendor vendor/boost-pfr/include)
target_include_directories(${t} PRIVATE vendor)
target_compile_definitions(${t} PRIVATE $<$<CONFIG:Debug>:DEBUG=1>)
if(GITREV_SHORT)
target_compile_definitions(${t} PRIVATE UPX_VERSION_GITREV="${GITREV_SHORT}${GITREV_PLUS}")
@@ -232,47 +463,68 @@ if(GITREV_SHORT)
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})
if(Threads_FOUND)
target_compile_definitions(${t} PRIVATE WITH_THREADS=1)
endif()
if(NOT UPX_CONFIG_DISABLE_WSTRICT)
target_compile_definitions(${t} PRIVATE UPX_CONFIG_DISABLE_WSTRICT=0)
endif()
if(NOT UPX_CONFIG_DISABLE_WERROR)
target_compile_definitions(${t} PRIVATE UPX_CONFIG_DISABLE_WERROR=0)
endif()
if(NOT UPX_CONFIG_DISABLE_BZIP2)
target_compile_definitions(${t} PRIVATE WITH_BZIP2=0) # FIXME TODO
endif()
if(NOT UPX_CONFIG_DISABLE_ZSTD)
target_compile_definitions(${t} PRIVATE WITH_ZSTD=1)
target_link_libraries(upx upx_vendor_zstd)
endif()
if(HAVE_UTIMENSAT)
target_compile_definitions(${t} PRIVATE USE_UTIMENSAT=1)
if(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
target_compile_definitions(${t} PRIVATE HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC=1)
endif()
endif()
# improve speed of the debug versions
upx_compile_source_debug_with_O2(src/compress/compress_lzma.cpp)
upx_compile_source_debug_with_O2(src/filter/filter_impl.cpp)
#upx_compile_target_debug_with_O2(${t})
upx_sanitize_target(${t})
if(MSVC_FRONTEND)
target_compile_options(${t} PRIVATE -EHsc ${warn_WN} ${warn_WX})
else()
target_compile_options(${t} PRIVATE ${warn_Wall} ${warn_Werror})
endif()
#***********************************************************************
# "ctest"
# "make test"
# "ninja test"
# ctest
# make test
# ninja test
#***********************************************************************
if(NOT UPX_CONFIG_CMAKE_DISABLE_TEST)
include(CTest)
# TODO later: check CMAKE_CROSSCOMPILING_EMULATOR
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!
# IMPORTANT NOTE: these tests can only work if the host executable format is supported by UPX!
function(upx_add_test)
set(name ${ARGV0})
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
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-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 -1 --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})
@@ -284,17 +536,17 @@ endif()
endif() # UPX_CONFIG_CMAKE_DISABLE_TEST
#***********************************************************************
# "cmake --install ."
# "make install"
# "ninja install"
# 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.")
#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)
@@ -302,7 +554,7 @@ 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
COPYING LICENSE NEWS README doc/THANKS.txt doc/upx-doc.html doc/upx-doc.txt
DESTINATION "${CMAKE_INSTALL_FULL_DOCDIR}"
)
install(FILES doc/upx.1 DESTINATION "${CMAKE_INSTALL_FULL_MANDIR}/man1")
@@ -314,36 +566,43 @@ endif() # UPX_CONFIG_CMAKE_DISABLE_INSTALL
# finally print some info about the build configuration
#***********************************************************************
function(print_var)
foreach(var ${ARGV})
if(${var})
message(STATUS "${var} = ${${var}}")
endif()
endforeach()
endfunction()
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()
print_var(CMAKE_VERSION UPX_CONFIG_CMAKE_MINIMUM_REQUIRED_VERSION CMAKE_GENERATOR)
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)
print_var(CMAKE_C_COMPILER_ID CMAKE_C_COMPILER_VERSION CMAKE_C_COMPILER_FRONTEND_VARIANT 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_FRONTEND_VARIANT CMAKE_CXX_COMPILER_ARCHITECTURE_ID CMAKE_CXX_PLATFORM_ID CMAKE_CXX_COMPILER_ABI)
print_var(CMAKE_POSITION_INDEPENDENT_CODE)
print_var(CYGWIN GNUC MINGW MSVC MSVC_FRONTEND MSVC_IDE WIN32 WIN64)
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)$")
if(CMAKE_BUILD_TYPE AND NOT CMAKE_BUILD_TYPE MATCHES "^(Debug|None|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 UPX_CONFIG_CMAKE_DISABLE_PLATFORM_CHECK)
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()
if(NOT ",${CMAKE_C_COMPILER_FRONTEND_VARIANT}," STREQUAL ",${CMAKE_CXX_COMPILER_FRONTEND_VARIANT},")
message(FATAL_ERROR "ERROR: CMAKE_C_COMPILER_FRONTEND_VARIANT CMAKE_CXX_COMPILER_FRONTEND_VARIANT mismatch")
endif()
endif() # UPX_CONFIG_CMAKE_DISABLE_PLATFORM_CHECK
# vim:set ft=cmake ts=4 sw=4 tw=0 et:
+22 -143
View File
@@ -1,19 +1,21 @@
#
# UPX top-level Makefile - needs GNU make and CMake >= 3.13
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
#
# 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:
# HINT: 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 ../.. # run config
# make -j # and run build
CMAKE = cmake
UPX_CMAKE_BUILD_FLAGS += --parallel
ifneq ($(VERBOSE),)
UPX_CMAKE_BUILD_FLAGS += --verbose
#UPX_CMAKE_BUILD_FLAGS += --verbose # requires CMake >= 3.14
UPX_CMAKE_CONFIG_FLAGS += -DCMAKE_VERBOSE_MAKEFILE=ON
endif
# enable this if you prefer Ninja for the actual builds:
#UPX_CMAKE_CONFIG_FLAGS += -G Ninja
@@ -38,149 +40,26 @@ 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"
.PHONY: PHONY
.SECONDEXPANSION:
.SUFFIXES:
# END of Makefile; extra stuff follows
# shortcuts (all => debug + release)
debug: build/debug
release: build/release
all build/all: build/debug build/release
build/%/all: $$(dir $$@)debug $$(dir $$@)release ;
#***********************************************************************
# extra builds: some pre-defined build configurations
#***********************************************************************
#
# END of Makefile
#
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
# extra pre-defined build configurations and some utility; optional
include ./misc/make/Makefile-extra.mk
# developer convenience
ifneq ($(wildcard /usr/bin/env),) # needs bash, perl, xargs, etc.
check-whitespace clang-format run-testsuite run-testsuite-debug run-testsuite-release: PHONY src/Makefile
$(MAKE) -C src $@
endif
endif
endif
#***********************************************************************
# check git submodules
#***********************************************************************
SUBMODULES = doctest lzma-sdk ucl valgrind zlib
dummy := $(foreach m,$(SUBMODULES),$(if $(wildcard vendor/$m/[CL]*),$m,\
$(error ERROR: missing git submodule $m; run 'git submodule update --init')))
+19 -9
View File
@@ -2,6 +2,17 @@
User visible changes for UPX
==================================================================
Changes in 4.2.0 (26 Oct 2023):
* win32/pe and win64/pe: stricter relocation checks; please report regressions
* new option '--link' to preserve hard-links (Unix only; use with care)
* add support for NO_COLOR env var; see https://no-color.org/
* disable macOS support until we fix compatibility with macOS 13+
* bug fixes - see https://github.com/upx/upx/milestone/13
Changes in 4.1.0 (08 Aug 2023):
* ELF: handle shared libraries with more than 2 PT_LOAD segments
* bug fixes - see https://github.com/upx/upx/milestone/11
Changes in 4.0.2 (30 Jan 2023):
* bug fixes - see https://github.com/upx/upx/milestone/9
@@ -75,7 +86,7 @@ Changes in 3.08 (12 Dec 2011):
* 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.
* 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.
@@ -149,7 +160,7 @@ Changes in 2.92 beta (23 Jan 2007):
Changes in 2.91 beta (29 Nov 2006):
* assorted bug fixes
* arm/pe: fix "missing" icon & version info resource problem for wince 5
* wince/arm: fix "missing" icon & version info resource problem for WinCE 5
* win32/pe & arm/pe: added option --compress-icons=3 to compress all icons
Changes in 2.90 beta (08 Oct 2006):
@@ -203,7 +214,7 @@ Changes in 1.95 beta (09 Apr 2006):
* win32/pe: really worked around R6002 runtime errors
Changes in 1.94 beta (11 Mar 2006):
* new format: added support for arm/pe (ARM executables running on WinCE)
* new format: added support for wince/arm (ARM executables running on WinCE)
* new format: added support for linux elf/amd64
* new format: added support for linux elf/ppc32
* new format: added support for mach/ppc32 (Apple Mac OS X)
@@ -255,7 +266,7 @@ Changes in 1.11 beta (20 Dec 2000):
==================================================================
Changes in 1.25 (29 Jun 2004)
* INFO: http://upx.sourceforge.net is the permanent UPX home page
* INFO: http://upx.sourceforge.net is the new UPX home page
* watcom/le: don't crash on files without relocations
* win32/pe: stricter checks of some PE values
* source code: much improved portability using ACC, the
@@ -520,12 +531,12 @@ Changes in 0.40 (05 Oct 1998)
* fixed a small but fatal bug in dos/sys introduced in 0.30
* fixed a rare bug in dos/exe
* worked around a bug in djgpp's strip 2.8
* djgpp/coff: Allegro packfile support should work now
* djgpp2/coff: Allegro packfile support should work now
* added dos/exeh compression method (works on 386+)
Changes in 0.30 (27 Jul 1998)
* fixed a serious bug in the 32-bit compressors - please don't use
djgpp/coff and watcom/le compressed files from previous versions,
djgpp2/coff and watcom/le compressed files from previous versions,
some of them are possibly damaged !
* the 16-bit uncompressors are a little bit shorter & faster
* fixed progress indicator for VESA and SVGA text modes
@@ -536,6 +547,5 @@ Changes in 0.20 (05 Jul 1998)
Changes in 0.05 (26 May 1998)
* first public beta release
# vim:set syntax=off tw=0 ts=4 sw=4 et: -*- coding: utf-8 -*-
* based on experience gained from our previous packers DJP (djgpp2/coff, 1996),
lzop (1996) and mfxpak (atari/tos, 1990)
+1 -1
View File
@@ -35,7 +35,7 @@ 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 programs and DLLs, macOS apps and Linux executables.
Windows programs and DLLs, and Linux executables.
UPX is free software distributed under the term of the GNU General
Public License. Full source code is available.
+36 -2
View File
@@ -44,7 +44,7 @@ Short overview
Tools needed to build/modify the UPX sources
--------------------------------------------
- A C++ compiler that supports C++ 17: clang-5, gcc-8 or msvc-2019 16.11
- A C++ compiler that fully implements 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
@@ -61,7 +61,7 @@ To compile the packer sources
If you want to modify the stub sources you'll also need
-------------------------------------------------------
- Podman/Docker: see misc/rebuild-stubs-with-podman - this
- Podman/Docker: see misc/podman/rebuild-stubs - this
is the preferred way of rebuilding the stubs
- otherwise you will need:
@@ -71,6 +71,40 @@ If you want to modify the stub sources you'll also need
https://github.com/upx/upx-stubtools/releases
Developer quick start
---------------------
1) $ mkdir my-upx; cd my-upx # new directory for safety and convenience
2) $ git clone https://github.com/upx/upx.git
3) $ git clone https://github.com/upx/upx-testsuite.git
4) # Optional for re-building stubs:
4a) $ pushd upx/src/stub # my-upx/upx/src/stub
4b) $ wget https://github.com/upx/upx-stubtools/releases/download/v20221212/bin-upx-20221212.tar.xz
# Extract to $HOME/bin/bin-upx or $HOME/local/bin/bin-upx.
# See directions in: https://github.com/upx/upx-stubtools
4c) $ make clean; make # verify that you can re-build stubs
4d) $ popd # my-upx
5) $ cd upx # my-upx/upx
6) $ git submodule update --init # compression algorithms, etc.
# DO NOT TOUCH vendor/...
# After a git merge/pull/etc, then use "git status"
# to check whether the vendor directory is clean;
# if not, then update via "git submodule update".
# If stuck, then reset via "rm -rf vendor; git submodule update --init".
7) $ mkdir -p build/debug build/release
8) $ pushd build/debug # my-upx/upx/build/debug
9) $ cmake ../.. # configure cmake
10) $ cmake --build . --verbose # optional "--verbose"
# This relies on stub/*.h, which YOU must re-build if necessary.
# When in doubt, then use "cd src/stub; make clean; make".
11) $ popd # my-upx/upx
12) $ cd src # my-upx/upx/src
12a) On MacOS: install homebrew (https:://brew.sh), then "brew install coreutils"
and put <some_prefix>/opt/coreutils/libexec/gnubin into PATH so that
"readlink -en" and "sha256sum -b" work.
13) $ make run-testsuite 2>&1 | tee testsuite.log
Misc. notes
-----------
-5
View File
@@ -1,5 +0,0 @@
-std=gnu++17
-Ivendor
-fno-strict-aliasing
-fno-strict-overflow
-funsigned-char
+3 -1
View File
@@ -41,12 +41,14 @@ Joergen Ibsen <jibz@hotmail.com> and d'b
for the relocation & address optimization ideas
John S. Fine <johnfine@erols.com>
for the new version of the dos/exe decompressor
Kornel Pal
for the EFI support
Lukundoo <Lukundoo@softhome.net>
for beta testing
Michael Devore
for initial dos/exe device driver support
Oleg V. Volkov <rover@lglobus.ru>
for various FreeBSD specific informations
for various FreeBSD specific information
The Owl & G-RoM
for the --compress-icons fix
Ralph Roth <RalphRoth@gmx.net>
+1 -1
View File
@@ -160,7 +160,7 @@ Copyright (c) 1996-2023 Markus Oberhumer, Laszlo Molnar &amp; John Reiser
<p>Info: An &quot;overlay&quot; 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&#39;t work with others, depending on how an application actually accesses this overlayed data.</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&#39;t work with others, depending on how an application actually accesses this overlaid data.</p>
<pre><code>--overlay=copy Copy any extra data attached to the file. [DEFAULT]
+1 -1
View File
@@ -153,7 +153,7 @@ OVERLAY HANDLING OPTIONS
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.
actually accesses this overlaid data.
--overlay=copy Copy any extra data attached to the file. [DEFAULT]
Generated
+2 -2
View File
@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "UPX 1"
.TH UPX 1 "2023-01-30" "upx 4.0.2" " "
.TH UPX 1 "2023-10-26" "upx 4.2.0" " "
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
@@ -296,7 +296,7 @@ it would be better to use resource sections).
\&\fB\s-1UPX\s0\fR 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.
actually accesses this overlaid data.
.PP
.Vb 1
\& \-\-overlay=copy Copy any extra data attached to the file. [DEFAULT]
+1 -1
View File
@@ -208,7 +208,7 @@ it would be better to use resource sections).
B<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.
actually accesses this overlaid data.
--overlay=copy Copy any extra data attached to the file. [DEFAULT]
@@ -0,0 +1,22 @@
# for clang-tidy-16 from https://clang.llvm.org/extra/clang-tidy/
---
Checks: >
-*,
bugprone-*,
-bugprone-branch-clone,
-bugprone-easily-swappable-parameters,
-bugprone-implicit-widening-of-multiplication-result,
-bugprone-macro-parentheses,
-bugprone-narrowing-conversions,
-bugprone-reserved-identifier,
-bugprone-switch-missing-default-case,
clang-analyzer-*,
-clang-analyzer-core.UndefinedBinaryOperatorResult,
-clang-analyzer-core.uninitialized.Assign,
-clang-analyzer-security.insecureAPI.strcpy,
clang-diagnostics-*',
performance-*,
FormatStyle: file
HeaderFilterRegex: '.*'
InheritParentConfig: false
...
@@ -0,0 +1,20 @@
# for clang-tidy-16 from https://clang.llvm.org/extra/clang-tidy/
---
Checks: >
-*,
bugprone-*,
-bugprone-assignment-in-if-condition,
-bugprone-easily-swappable-parameters,
-bugprone-implicit-widening-of-multiplication-result,
-bugprone-macro-parentheses,
-bugprone-reserved-identifier,
-bugprone-sizeof-expression,
-bugprone-suspicious-include,
clang-analyzer-*,
-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,
clang-diagnostics-*',
performance-*,
FormatStyle: file
HeaderFilterRegex: '.*'
InheritParentConfig: false
...
@@ -0,0 +1,21 @@
# for clang-tidy-16 from https://clang.llvm.org/extra/clang-tidy/
---
Checks: >
-*,
bugprone-*,
-bugprone-assignment-in-if-condition,
-bugprone-easily-swappable-parameters,
-bugprone-implicit-widening-of-multiplication-result,
-bugprone-macro-parentheses,
-bugprone-narrowing-conversions,
-bugprone-reserved-identifier,
-bugprone-switch-missing-default-case,
clang-analyzer-*,
-clang-analyzer-optin.performance.Padding,
-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,
clang-diagnostics-*',
performance-*,
FormatStyle: file
HeaderFilterRegex: '.*'
InheritParentConfig: false
...
@@ -0,0 +1,25 @@
# for clang-tidy-16 from https://clang.llvm.org/extra/clang-tidy/
---
Checks: >
-*,
bugprone-*,
-bugprone-assignment-in-if-condition,
-bugprone-branch-clone,
-bugprone-easily-swappable-parameters,
-bugprone-implicit-widening-of-multiplication-result,
-bugprone-macro-parentheses,
-bugprone-misplaced-widening-cast,
-bugprone-narrowing-conversions,
-bugprone-reserved-identifier,
-bugprone-switch-missing-default-case,
clang-analyzer-*,
-clang-analyzer-core.UndefinedBinaryOperatorResult,
-clang-analyzer-deadcode.DeadStores,
-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,
clang-diagnostics-*',
performance-*,
-performance-no-int-to-ptr,
FormatStyle: file
HeaderFilterRegex: '.*'
InheritParentConfig: false
...
+549
View File
@@ -0,0 +1,549 @@
#!/usr/bin/env python3
#
# ===- run-clang-tidy.py - Parallel clang-tidy runner --------*- python -*--===#
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
# ===-----------------------------------------------------------------------===#
# FIXME: Integrate with clang-tidy-diff.py
"""
Parallel clang-tidy runner
==========================
Runs clang-tidy over all files in a compilation database. Requires clang-tidy
and clang-apply-replacements in $PATH.
Example invocations.
- Run clang-tidy on all files in the current working directory with a default
set of checks and show warnings in the cpp files and all project headers.
run-clang-tidy.py $PWD
- Fix all header guards.
run-clang-tidy.py -fix -checks=-*,llvm-header-guard
- Fix all header guards included from clang-tidy and header guards
for clang-tidy headers.
run-clang-tidy.py -fix -checks=-*,llvm-header-guard extra/clang-tidy \
-header-filter=extra/clang-tidy
Compilation database setup:
http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
"""
from __future__ import print_function
import argparse
import glob
import json
import multiprocessing
import os
import queue
import re
import shutil
import subprocess
import sys
import tempfile
import threading
import traceback
try:
import yaml
except ImportError:
yaml = None
def strtobool(val):
"""Convert a string representation of truth to a bool following LLVM's CLI argument parsing."""
val = val.lower()
if val in ["", "true", "1"]:
return True
elif val in ["false", "0"]:
return False
# Return ArgumentTypeError so that argparse does not substitute its own error message
raise argparse.ArgumentTypeError(
"'{}' is invalid value for boolean argument! Try 0 or 1.".format(val)
)
def find_compilation_database(path):
"""Adjusts the directory until a compilation database is found."""
result = os.path.realpath("./")
while not os.path.isfile(os.path.join(result, path)):
parent = os.path.dirname(result)
if result == parent:
print("Error: could not find compilation database.")
sys.exit(1)
result = parent
return result
def make_absolute(f, directory):
if os.path.isabs(f):
return f
return os.path.normpath(os.path.join(directory, f))
def get_tidy_invocation(
f,
clang_tidy_binary,
checks,
tmpdir,
build_path,
header_filter,
allow_enabling_alpha_checkers,
extra_arg,
extra_arg_before,
quiet,
config_file_path,
config,
line_filter,
use_color,
plugins,
warnings_as_errors,
):
"""Gets a command line for clang-tidy."""
start = [clang_tidy_binary]
if allow_enabling_alpha_checkers:
start.append("-allow-enabling-analyzer-alpha-checkers")
if header_filter is not None:
start.append("-header-filter=" + header_filter)
if line_filter is not None:
start.append("-line-filter=" + line_filter)
if use_color is not None:
if use_color:
start.append("--use-color")
else:
start.append("--use-color=false")
if checks:
start.append("-checks=" + checks)
if tmpdir is not None:
start.append("-export-fixes")
# Get a temporary file. We immediately close the handle so clang-tidy can
# overwrite it.
(handle, name) = tempfile.mkstemp(suffix=".yaml", dir=tmpdir)
os.close(handle)
start.append(name)
for arg in extra_arg:
start.append("-extra-arg=%s" % arg)
for arg in extra_arg_before:
start.append("-extra-arg-before=%s" % arg)
start.append("-p=" + build_path)
if quiet:
start.append("-quiet")
if config_file_path:
start.append("--config-file=" + config_file_path)
elif config:
start.append("-config=" + config)
for plugin in plugins:
start.append("-load=" + plugin)
if warnings_as_errors:
start.append("--warnings-as-errors=" + warnings_as_errors)
start.append(f)
return start
def merge_replacement_files(tmpdir, mergefile):
"""Merge all replacement files in a directory into a single file"""
# The fixes suggested by clang-tidy >= 4.0.0 are given under
# the top level key 'Diagnostics' in the output yaml files
mergekey = "Diagnostics"
merged = []
for replacefile in glob.iglob(os.path.join(tmpdir, "*.yaml")):
content = yaml.safe_load(open(replacefile, "r"))
if not content:
continue # Skip empty files.
merged.extend(content.get(mergekey, []))
if merged:
# MainSourceFile: The key is required by the definition inside
# include/clang/Tooling/ReplacementsYaml.h, but the value
# is actually never used inside clang-apply-replacements,
# so we set it to '' here.
output = {"MainSourceFile": "", mergekey: merged}
with open(mergefile, "w") as out:
yaml.safe_dump(output, out)
else:
# Empty the file:
open(mergefile, "w").close()
def find_binary(arg, name, build_path):
"""Get the path for a binary or exit"""
if arg:
if shutil.which(arg):
return arg
else:
raise SystemExit(
"error: passed binary '{}' was not found or is not executable".format(
arg
)
)
built_path = os.path.join(build_path, "bin", name)
binary = shutil.which(name) or shutil.which(built_path)
if binary:
return binary
else:
raise SystemExit(
"error: failed to find {} in $PATH or at {}".format(name, built_path)
)
def apply_fixes(args, clang_apply_replacements_binary, tmpdir):
"""Calls clang-apply-fixes on a given directory."""
invocation = [clang_apply_replacements_binary]
invocation.append("-ignore-insert-conflict")
if args.format:
invocation.append("-format")
if args.style:
invocation.append("-style=" + args.style)
invocation.append(tmpdir)
subprocess.call(invocation)
def run_tidy(args, clang_tidy_binary, tmpdir, build_path, queue, lock, failed_files):
"""Takes filenames out of queue and runs clang-tidy on them."""
while True:
name = queue.get()
invocation = get_tidy_invocation(
name,
clang_tidy_binary,
args.checks,
tmpdir,
build_path,
args.header_filter,
args.allow_enabling_alpha_checkers,
args.extra_arg,
args.extra_arg_before,
args.quiet,
args.config_file,
args.config,
args.line_filter,
args.use_color,
args.plugins,
args.warnings_as_errors,
)
proc = subprocess.Popen(
invocation, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
output, err = proc.communicate()
if proc.returncode != 0:
if proc.returncode < 0:
msg = "%s: terminated by signal %d\n" % (name, -proc.returncode)
err += msg.encode("utf-8")
failed_files.append(name)
with lock:
sys.stdout.write(" ".join(invocation) + "\n" + output.decode("utf-8"))
if len(err) > 0:
sys.stdout.flush()
sys.stderr.write(err.decode("utf-8"))
queue.task_done()
def main():
parser = argparse.ArgumentParser(
description="Runs clang-tidy over all files "
"in a compilation database. Requires "
"clang-tidy and clang-apply-replacements in "
"$PATH or in your build directory."
)
parser.add_argument(
"-allow-enabling-alpha-checkers",
action="store_true",
help="allow alpha checkers from " "clang-analyzer.",
)
parser.add_argument(
"-clang-tidy-binary", metavar="PATH", help="path to clang-tidy binary"
)
parser.add_argument(
"-clang-apply-replacements-binary",
metavar="PATH",
help="path to clang-apply-replacements binary",
)
parser.add_argument(
"-checks",
default=None,
help="checks filter, when not specified, use clang-tidy " "default",
)
config_group = parser.add_mutually_exclusive_group()
config_group.add_argument(
"-config",
default=None,
help="Specifies a configuration in YAML/JSON format: "
" -config=\"{Checks: '*', "
' CheckOptions: {x: y}}" '
"When the value is empty, clang-tidy will "
"attempt to find a file named .clang-tidy for "
"each source file in its parent directories.",
)
config_group.add_argument(
"-config-file",
default=None,
help="Specify the path of .clang-tidy or custom config "
"file: e.g. -config-file=/some/path/myTidyConfigFile. "
"This option internally works exactly the same way as "
"-config option after reading specified config file. "
"Use either -config-file or -config, not both.",
)
parser.add_argument(
"-header-filter",
default=None,
help="regular expression matching the names of the "
"headers to output diagnostics from. Diagnostics from "
"the main file of each translation unit are always "
"displayed.",
)
parser.add_argument(
"-line-filter",
default=None,
help="List of files with line ranges to filter the" "warnings.",
)
if yaml:
parser.add_argument(
"-export-fixes",
metavar="file_or_directory",
dest="export_fixes",
help="A directory or a yaml file to store suggested fixes in, "
"which can be applied with clang-apply-replacements. If the "
"parameter is a directory, the fixes of each compilation unit are "
"stored in individual yaml files in the directory.",
)
else:
parser.add_argument(
"-export-fixes",
metavar="directory",
dest="export_fixes",
help="A directory to store suggested fixes in, which can be applied "
"with clang-apply-replacements. The fixes of each compilation unit are "
"stored in individual yaml files in the directory.",
)
parser.add_argument(
"-j",
type=int,
default=0,
help="number of tidy instances to be run in parallel.",
)
parser.add_argument(
"files", nargs="*", default=[".*"], help="files to be processed (regex on path)"
)
parser.add_argument("-fix", action="store_true", help="apply fix-its")
parser.add_argument(
"-format", action="store_true", help="Reformat code " "after applying fixes"
)
parser.add_argument(
"-style",
default="file",
help="The style of reformat " "code after applying fixes",
)
parser.add_argument(
"-use-color",
type=strtobool,
nargs="?",
const=True,
help="Use colors in diagnostics, overriding clang-tidy's"
" default behavior. This option overrides the 'UseColor"
"' option in .clang-tidy file, if any.",
)
parser.add_argument(
"-p", dest="build_path", help="Path used to read a compile command database."
)
parser.add_argument(
"-extra-arg",
dest="extra_arg",
action="append",
default=[],
help="Additional argument to append to the compiler " "command line.",
)
parser.add_argument(
"-extra-arg-before",
dest="extra_arg_before",
action="append",
default=[],
help="Additional argument to prepend to the compiler " "command line.",
)
parser.add_argument(
"-quiet", action="store_true", help="Run clang-tidy in quiet mode"
)
parser.add_argument(
"-load",
dest="plugins",
action="append",
default=[],
help="Load the specified plugin in clang-tidy.",
)
parser.add_argument(
"-warnings-as-errors",
default=None,
help="Upgrades warnings to errors. Same format as " "'-checks'",
)
args = parser.parse_args()
db_path = "compile_commands.json"
if args.build_path is not None:
build_path = args.build_path
else:
# Find our database
build_path = find_compilation_database(db_path)
clang_tidy_binary = find_binary(args.clang_tidy_binary, "clang-tidy", build_path)
if args.fix:
clang_apply_replacements_binary = find_binary(
args.clang_apply_replacements_binary, "clang-apply-replacements", build_path
)
combine_fixes = False
export_fixes_dir = None
delete_fixes_dir = False
if args.export_fixes is not None:
# if a directory is given, create it if it does not exist
if args.export_fixes.endswith(os.path.sep) and not os.path.isdir(
args.export_fixes
):
os.makedirs(args.export_fixes)
if not os.path.isdir(args.export_fixes):
if not yaml:
raise RuntimeError(
"Cannot combine fixes in one yaml file. Either install PyYAML or specify an output directory."
)
combine_fixes = True
if os.path.isdir(args.export_fixes):
export_fixes_dir = args.export_fixes
if export_fixes_dir is None and (args.fix or combine_fixes):
export_fixes_dir = tempfile.mkdtemp()
delete_fixes_dir = True
# Load the database and extract all files.
database = json.load(open(os.path.join(build_path, db_path)))
files = set(
[make_absolute(entry["file"], entry["directory"]) for entry in database]
)
# Build up a big regexy filter from all command line arguments.
file_name_re = re.compile("|".join(args.files))
# filter files with mo.group(0), and sort files
matched_files = []
for name in files:
mo = file_name_re.search(name)
if mo and mo.group(0):
matched_files.append(name)
files = sorted(matched_files)
if not files:
if delete_fixes_dir:
shutil.rmtree(export_fixes_dir)
sys.exit(0)
try:
invocation = get_tidy_invocation(
"",
clang_tidy_binary,
args.checks,
None,
build_path,
args.header_filter,
args.allow_enabling_alpha_checkers,
args.extra_arg,
args.extra_arg_before,
args.quiet,
args.config_file,
args.config,
args.line_filter,
args.use_color,
args.plugins,
args.warnings_as_errors,
)
invocation.append("-list-checks")
invocation.append("-")
if args.quiet:
# Even with -quiet we still want to check if we can call clang-tidy.
with open(os.devnull, "w") as dev_null:
subprocess.check_call(invocation, stdout=dev_null)
else:
subprocess.check_call(invocation)
except:
print("Unable to run clang-tidy.", file=sys.stderr)
sys.exit(1)
max_task = args.j
if max_task == 0:
max_task = multiprocessing.cpu_count()
return_code = 0
try:
# Spin up a bunch of tidy-launching threads.
task_queue = queue.Queue(max_task)
# List of files with a non-zero return code.
failed_files = []
lock = threading.Lock()
for _ in range(max_task):
t = threading.Thread(
target=run_tidy,
args=(
args,
clang_tidy_binary,
export_fixes_dir,
build_path,
task_queue,
lock,
failed_files,
),
)
t.daemon = True
t.start()
# Fill the queue with files.
for name in files:
if file_name_re.search(name):
task_queue.put(name)
# Wait for all threads to be done.
task_queue.join()
if len(failed_files):
return_code = 1
except KeyboardInterrupt:
# This is a sad hack. Unfortunately subprocess goes
# bonkers with ctrl-c and we start forking merrily.
print("\nCtrl-C detected, goodbye.")
if delete_fixes_dir:
shutil.rmtree(export_fixes_dir)
os.kill(0, 9)
if combine_fixes:
print("Writing fixes to " + args.export_fixes + " ...")
try:
merge_replacement_files(export_fixes_dir, args.export_fixes)
except:
print("Error exporting fixes.\n", file=sys.stderr)
traceback.print_exc()
return_code = 1
if args.fix:
print("Applying fixes ...")
try:
apply_fixes(args, clang_apply_replacements_binary, export_fixes_dir)
except:
print("Error applying fixes.\n", file=sys.stderr)
traceback.print_exc()
return_code = 1
if delete_fixes_dir:
shutil.rmtree(export_fixes_dir)
sys.exit(return_code)
if __name__ == "__main__":
main()
+251
View File
@@ -0,0 +1,251 @@
#
# UPX top-level Makefile - needs GNU make and CMake >= 3.13
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
#
#***********************************************************************
# 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 clang/clang++ -static
build/extra/clang-static/debug: PHONY; $(call run_config_and_build,$@,Debug)
build/extra/clang-static/release: PHONY; $(call run_config_and_build,$@,Release)
build/extra/clang-static/%: export CC = clang -static
build/extra/clang-static/%: export CXX = clang++ -static
# force building with clang/clang++ -static -flto
build/extra/clang-static-lto/debug: PHONY; $(call run_config_and_build,$@,Debug)
build/extra/clang-static-lto/release: PHONY; $(call run_config_and_build,$@,Release)
build/extra/clang-static-lto/%: export CC = clang -static -flto
build/extra/clang-static-lto/%: export CXX = clang++ -static -flto
# force building with clang/clang++ C17/C++20
build/extra/clang-std-cxx20/debug: PHONY; $(call run_config_and_build,$@,Debug)
build/extra/clang-std-cxx20/release: PHONY; $(call run_config_and_build,$@,Release)
build/extra/clang-std-cxx20/%: export CC = clang -std=gnu17
build/extra/clang-std-cxx20/%: export CXX = clang++ -std=gnu++20
build/extra/clang-std-cxx20/%: export UPX_CONFIG_DISABLE_C_STANDARD=ON
build/extra/clang-std-cxx20/%: export UPX_CONFIG_DISABLE_CXX_STANDARD=ON
# force building with clang/clang++ C23/C++23
build/extra/clang-std-cxx23/debug: PHONY; $(call run_config_and_build,$@,Debug)
build/extra/clang-std-cxx23/release: PHONY; $(call run_config_and_build,$@,Release)
build/extra/clang-std-cxx23/%: export CC = clang -std=gnu2x
build/extra/clang-std-cxx23/%: export CXX = clang++ -std=gnu++2b
build/extra/clang-std-cxx23/%: export UPX_CONFIG_DISABLE_C_STANDARD=ON
build/extra/clang-std-cxx23/%: export UPX_CONFIG_DISABLE_CXX_STANDARD=ON
# 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 gcc/g++ -static
build/extra/gcc-static/debug: PHONY; $(call run_config_and_build,$@,Debug)
build/extra/gcc-static/release: PHONY; $(call run_config_and_build,$@,Release)
build/extra/gcc-static/%: export CC = gcc -static
build/extra/gcc-static/%: export CXX = g++ -static
# force building with gcc/g++ -static -flto
build/extra/gcc-static-lto/debug: PHONY; $(call run_config_and_build,$@,Debug)
build/extra/gcc-static-lto/release: PHONY; $(call run_config_and_build,$@,Release)
build/extra/gcc-static-lto/%: export CC = gcc -static -flto
build/extra/gcc-static-lto/%: export CXX = g++ -static -flto
# force building with gcc/g++ C17/C++20
build/extra/gcc-std-cxx20/debug: PHONY; $(call run_config_and_build,$@,Debug)
build/extra/gcc-std-cxx20/release: PHONY; $(call run_config_and_build,$@,Release)
build/extra/gcc-std-cxx20/%: export CC = gcc -std=gnu17
build/extra/gcc-std-cxx20/%: export CXX = g++ -std=gnu++20
build/extra/gcc-std-cxx20/%: export UPX_CONFIG_DISABLE_C_STANDARD=ON
build/extra/gcc-std-cxx20/%: export UPX_CONFIG_DISABLE_CXX_STANDARD=ON
# force building with gcc/g++ C23/C++23
build/extra/gcc-std-cxx23/debug: PHONY; $(call run_config_and_build,$@,Debug)
build/extra/gcc-std-cxx23/release: PHONY; $(call run_config_and_build,$@,Release)
build/extra/gcc-std-cxx23/%: export CC = gcc -std=gnu2x
build/extra/gcc-std-cxx23/%: export CXX = g++ -std=gnu++23
build/extra/gcc-std-cxx23/%: export UPX_CONFIG_DISABLE_C_STANDARD=ON
build/extra/gcc-std-cxx23/%: export UPX_CONFIG_DISABLE_CXX_STANDARD=ON
# cross compiler: Linux glibc aarch64-linux-gnu (arm64)
build/extra/cross-linux-gnu-aarch64/debug: PHONY; $(call run_config_and_build,$@,Debug)
build/extra/cross-linux-gnu-aarch64/release: PHONY; $(call run_config_and_build,$@,Release)
build/extra/cross-linux-gnu-aarch64/%: export CC = aarch64-linux-gnu-gcc
build/extra/cross-linux-gnu-aarch64/%: export CXX = aarch64-linux-gnu-g++
# cross compiler: Linux glibc arm-linux-gnueabihf
build/extra/cross-linux-gnu-arm-eabihf/debug: PHONY; $(call run_config_and_build,$@,Debug)
build/extra/cross-linux-gnu-arm-eabihf/release: PHONY; $(call run_config_and_build,$@,Release)
build/extra/cross-linux-gnu-arm-eabihf/%: export CC = arm-linux-gnueabihf-gcc
build/extra/cross-linux-gnu-arm-eabihf/%: export CXX = arm-linux-gnueabihf-g++ -Wno-psabi
# cross compiler: Windows x86 win32 MinGW (i386)
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 -static
build/extra/cross-windows-mingw32/%: export CXX = i686-w64-mingw32-g++ -static
# cross compiler: Windows x64 win64 MinGW (amd64)
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 -static
build/extra/cross-windows-mingw64/%: export CXX = x86_64-w64-mingw32-g++ -static
# cross compiler: macOS arm64 (aarch64)
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 (amd64)
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
#***********************************************************************
# C/C++ static analyzers
#***********************************************************************
# force building with clang Static Analyzer (scan-build)
SCAN_BUILD = scan-build
build/analyze/clang-analyzer/debug: PHONY; $(call run_config_and_build,$@,Debug)
build/analyze/clang-analyzer/release: PHONY; $(call run_config_and_build,$@,Release)
build/analyze/clang-analyzer/%: override CMAKE := $(SCAN_BUILD) $(CMAKE)
build/analyze/clang-analyzer/%: export CCC_CC ?= clang
build/analyze/clang-analyzer/%: export CCC_CXX ?= clang++
# run clang-tidy: uses file compile_commands.json from an existing clang build
# does not create any actual files, so purely PHONY
RUN_CLANG_TIDY = time python3 ./misc/analyze/clang-tidy/run-clang-tidy.py -p $<
RUN_CLANG_TIDY_WERROR = $(RUN_CLANG_TIDY) '-warnings-as-errors=*'
build/analyze/clang-tidy-upx/debug build/analyze/clang-tidy-upx/release: build/extra/clang/$$(notdir $$@) PHONY
$(RUN_CLANG_TIDY_WERROR) -config-file ./.clang-tidy '/src/.*\.cpp'
build/analyze/clang-tidy-bzip2/debug build/analyze/clang-tidy-bzip2/release: build/extra/clang/$$(notdir $$@) PHONY
$(RUN_CLANG_TIDY) -config-file ./misc/analyze/clang-tidy/clang-tidy-bzip2.yml /vendor/bzip2/
build/analyze/clang-tidy-ucl/debug build/analyze/clang-tidy-ucl/release: build/extra/clang/$$(notdir $$@) PHONY
$(RUN_CLANG_TIDY_WERROR) -config-file ./misc/analyze/clang-tidy/clang-tidy-ucl.yml /vendor/ucl/
build/analyze/clang-tidy-zlib/debug build/analyze/clang-tidy-zlib/release: build/extra/clang/$$(notdir $$@) PHONY
$(RUN_CLANG_TIDY_WERROR) -config-file ./misc/analyze/clang-tidy/clang-tidy-zlib.yml /vendor/zlib/
build/analyze/clang-tidy-zstd/debug build/analyze/clang-tidy-zstd/release: build/extra/clang/$$(notdir $$@) PHONY
$(RUN_CLANG_TIDY) -config-file ./misc/analyze/clang-tidy/clang-tidy-zstd.yml /vendor/zstd/
build/analyze/clang-tidy/debug build/analyze/clang-tidy/release: build/analyze/clang-tidy-upx/$$(notdir $$@)
build/analyze/clang-tidy/debug build/analyze/clang-tidy/release: build/analyze/clang-tidy-bzip2/$$(notdir $$@)
build/analyze/clang-tidy/debug build/analyze/clang-tidy/release: build/analyze/clang-tidy-ucl/$$(notdir $$@)
build/analyze/clang-tidy/debug build/analyze/clang-tidy/release: build/analyze/clang-tidy-zlib/$$(notdir $$@)
build/analyze/clang-tidy/debug build/analyze/clang-tidy/release: build/analyze/clang-tidy-zstd/$$(notdir $$@)
# OLD names [deprecated]
build/extra/scan-build/debug: build/analyze/clang-analyzer/debug
build/extra/scan-build/release: build/analyze/clang-analyzer/release
#***********************************************************************
# 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/all: xtarget/debug xtarget/release
xtarget/debug: build/xtarget/$(UPX_XTARGET)/debug
xtarget/release: build/xtarget/$(UPX_XTARGET)/release
# set new default
.DEFAULT_GOAL = xtarget/release
endif
endif
endif
#***********************************************************************
# assemble cmake config flags; useful for CI jobs
#***********************************************************************
ifneq ($(origin UPX_CMAKE_CONFIG_FLAGS),command line) # needed to work around a GNU make bug
# info: by default CMake only honors the CC and CXX environment variables; make
# it easy to set other variables like CMAKE_AR or CMAKE_RANLIB
__add_cmake_config = $(and $($1),-D$1="$($1)")
# pass common CMake settings from environment/make to cmake
build/%: UPX_CMAKE_CONFIG_FLAGS += $(call __add_cmake_config,CMAKE_AR)
build/%: UPX_CMAKE_CONFIG_FLAGS += $(call __add_cmake_config,CMAKE_NM)
build/%: UPX_CMAKE_CONFIG_FLAGS += $(call __add_cmake_config,CMAKE_RANLIB)
build/%: UPX_CMAKE_CONFIG_FLAGS += $(call __add_cmake_config,CMAKE_OBJCOPY)
build/%: UPX_CMAKE_CONFIG_FLAGS += $(call __add_cmake_config,CMAKE_OBJDUMP)
build/%: UPX_CMAKE_CONFIG_FLAGS += $(call __add_cmake_config,CMAKE_STRIP)
# pass UPX config options from environment/make to cmake; see CMakeLists.txt
build/%: UPX_CMAKE_CONFIG_FLAGS += $(call __add_cmake_config,UPX_CONFIG_DISABLE_GITREV)
build/%: UPX_CMAKE_CONFIG_FLAGS += $(call __add_cmake_config,UPX_CONFIG_DISABLE_SANITIZE)
build/%: UPX_CMAKE_CONFIG_FLAGS += $(call __add_cmake_config,UPX_CONFIG_DISABLE_WSTRICT)
build/%: UPX_CMAKE_CONFIG_FLAGS += $(call __add_cmake_config,UPX_CONFIG_DISABLE_WERROR)
build/%: UPX_CMAKE_CONFIG_FLAGS += $(call __add_cmake_config,UPX_CONFIG_DISABLE_SELF_PACK_TEST)
endif # bug work-around
#***********************************************************************
# check git submodules
#***********************************************************************
SUBMODULES = doctest lzma-sdk ucl valgrind zlib
dummy := $(foreach m,$(SUBMODULES),$(if $(wildcard vendor/$m/[CL]*),$m,\
$(error ERROR: missing git submodule '$m'; run 'git submodule update --init')))
@@ -6,12 +6,14 @@ 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,
# NOTE: this image is based on rebuild-stubs/upx-stubtools-20221212-v6,
# 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
image=upx-cross-compile-ubuntu2204-20230721-v1
[[ $1 == --print-image ]] && echo "$image" && exit 0
podman build -t "$image" -f "$argv0dir/Dockerfile" "$argv0dir"
podman image list "$image"
echo
podman image tree "$image"
+40
View File
@@ -0,0 +1,40 @@
#! /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")"
# list all system packages that are installed in the image
# using a rootless Podman container
image="$("$argv0dir/10-create-image.sh" --print-image)"
podman image list "$image"
echo
podman image tree "$image"
echo 'Packages:'
flags=( --read-only --rm --pull=never )
flags+=( --cap-drop=all ) # drop all capabilities
flags+=( --network=none ) # no network needed
podman run "${flags[@]}" "$image" bash -c $'dpkg -l | sed \'s/ *$//\' | LC_ALL=C sort'
echo
echo 'Packages sorted by Installed-Size:'
podman run "${flags[@]}" "$image" bash -c $'awk \'
BEGIN {
arch = "UNKNOWN"; size = 0; package = "UNKNOWN";
}
{
if ($1 == "Architecture:") arch = $2;
if ($1 == "Installed-Size:") size = $2;
if ($1 == "Package:") package = $2;
if ($1 == "") {
printf("%9d %-40s %s\\n", size, package, arch);
count += 1; total += size;
arch = "UNKNOWN"; size = 0; package = "UNKNOWN";
}
}
END {
printf("%9d ===== TOTAL (%d packages)\\n", total, count);
}
\' /var/lib/dpkg/status | LC_ALL=C sort -rn'
@@ -6,12 +6,12 @@ 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
image="$("$argv0dir/10-create-image.sh" --print-image)"
flags=( -ti --read-only --rm )
flags=( --read-only --rm --pull=never )
flags+=( --cap-drop=all ) # drop all capabilities
flags+=( --network=none ) # no network needed
flags+=( -e TERM="$TERM" ) # pass $TERM
flags+=( -ti -e TERM="$TERM" ) # allocate an interactive pseudo-tty and pass $TERM
if [[ 1 == 1 ]]; then
# run as user upx 2000:2000
flags+=( --user 2000 )
@@ -21,8 +21,10 @@ if [[ 1 == 1 ]]; then
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+=( -v "${argv0dir}/../../..:/home/upx/src/upx" )
flags+=( -w /home/upx/src/upx ) # set working directory
flags+=( --tmpfs /home/upx/.cache:rw,exec ) # mount a writeable tmpfs
flags+=( --tmpfs /home/upx/.local:rw,exec ) # mount a writeable tmpfs
else
# run as user root 0:0
# ONLY FOR DEBUGGING THE IMAGE
@@ -30,7 +32,11 @@ else
flags+=( --user 0 )
fi
podman run "${flags[@]}" "$image" bash -l
if [[ $# == 0 ]]; then
podman run "${flags[@]}" "$image" bash -l
else
podman run "${flags[@]}" "$image" "$@"
fi
# now we can cross-compile UPX for Windows:
# cd /home/upx/src/upx
@@ -44,10 +50,11 @@ podman run "${flags[@]}" "$image" bash -l
# 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
# and finally see
# ./misc/podman/cross-compile-upx-ubuntu/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
# cd /home/upx/src/upx/build/cross-compile-upx-ubuntu2204/alpha-linux-gnu/debug
# qemu-alpha -L /usr/alpha-linux-gnu ./upx --version
# cd /home/upx/src/upx/build/cross-compile-upx-ubuntu2204/hppa-linux-gnu/debug
# qemu-hppa -L /usr/hppa-linux-gnu ./upx --version
# (similar for many other architectures/builds)
@@ -1,8 +1,8 @@
# NOTE: this image is based on rebuild-stubs-with-podman/upx-stubtools-20221212-v4,
# NOTE: this image is based on rebuild-stubs/upx-stubtools-20221212-v6,
# 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
FROM localhost/upx-stubtools-20221212-v6
ENV UPX_CONTAINER_IMAGE_NAME=upx-cross-compile-ubuntu2204-20230721-v1
ARG DEBIAN_FRONTEND=noninteractive
USER root
@@ -39,7 +39,7 @@ 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 \
qemu-system qemu-user wine wine32:i386 wine64 \
# misc
gdb lsb-release valgrind \
&& true
@@ -50,5 +50,5 @@ RUN cd /usr/bin \
&& ln -s -v ../../bin/yaml2obj-14 /usr/local/bin/llvm-yaml2obj \
&& true
# switch back to default user upx 2000:2000
# switch back to default user upx:upx 2000:2000
USER upx
@@ -13,9 +13,10 @@ if [[ $UPX_CONTAINER_IMAGE_NAME != upx-cross-compile-* ]]; then
fi
# go to upx top-level directory
cd "$argv0dir/../.." || exit 1
cd "$argv0dir/../../.." || exit 1
pwd
[[ -f src/version.h ]] || exit 1 # sanity check
test -f doc/upx.pod || exit 1 # sanity check
test -f src/version.h || exit 1 # sanity check
function run_config_and_build {
# requires: AR CC CXX RANLIB
@@ -27,9 +28,13 @@ function run_config_and_build {
# 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 sanitize link errors with current MinGW-w64 versions; link libstdc++ statically
i686-w64-mingw32)
cmake_config_flags=-DUPX_CONFIG_DISABLE_SANITIZE=ON
CC="$CC -static"; CXX="$CXX -static" ;;
x86_64-w64-mingw32)
cmake_config_flags=-DUPX_CONFIG_DISABLE_SANITIZE=ON
CC="$CC -static"; CXX="$CXX -static" ;;
# avoid warnings about arm libstdc++ ABI change in gcc-7
arm-linux-*) CXX="$CXX -Wno-psabi" ;;
esac
@@ -39,14 +44,15 @@ function run_config_and_build {
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
bdir="build/cross-compile-upx-ubuntu2204/$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
export CMAKE_REQUIRED_QUIET=OFF
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
cmake --build "$bdir" --config $build_type --parallel
done
}
@@ -87,7 +93,7 @@ do
export CC=/usr/bin/${toolchain}-gcc
export CXX=/usr/bin/${toolchain}-g++
export RANLIB=/usr/bin/${toolchain}-ranlib
ls -l $AR $CC $CXX $RANLIB
ls -l "$AR" "$CC" "$CXX" "$RANLIB"
run_config_and_build $toolchain
unset AR CC CXX RANLIB
done
File diff suppressed because it is too large Load Diff
@@ -6,9 +6,11 @@ argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
# create the image from Dockerfile
# using a rootless Podman container
image=upx-stubtools-20221212-v4
image=upx-stubtools-20221212-v6
[[ $1 == --print-image ]] && echo "$image" && exit 0
podman build -t "$image" -f "$argv0dir/Dockerfile" "$argv0dir"
podman image list "$image"
echo
podman image tree "$image"
+40
View File
@@ -0,0 +1,40 @@
#! /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")"
# list all system packages that are installed in the image
# using a rootless Podman container
image="$("$argv0dir/10-create-image.sh" --print-image)"
podman image list "$image"
echo
podman image tree "$image"
echo 'Packages:'
flags=( --read-only --rm --pull=never )
flags+=( --cap-drop=all ) # drop all capabilities
flags+=( --network=none ) # no network needed
podman run "${flags[@]}" "$image" bash -c $'dpkg -l | sed \'s/ *$//\' | LC_ALL=C sort'
echo
echo 'Packages sorted by Installed-Size:'
podman run "${flags[@]}" "$image" bash -c $'awk \'
BEGIN {
arch = "UNKNOWN"; size = 0; package = "UNKNOWN";
}
{
if ($1 == "Architecture:") arch = $2;
if ($1 == "Installed-Size:") size = $2;
if ($1 == "Package:") package = $2;
if ($1 == "") {
printf("%9d %-40s %s\\n", size, package, arch);
count += 1; total += size;
arch = "UNKNOWN"; size = 0; package = "UNKNOWN";
}
}
END {
printf("%9d ===== TOTAL (%d packages)\\n", total, count);
}
\' /var/lib/dpkg/status | LC_ALL=C sort -rn'
@@ -6,12 +6,12 @@ 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
image="$("$argv0dir/10-create-image.sh" --print-image)"
flags=( -ti --read-only --rm )
flags=( --read-only --rm --pull=never )
flags+=( --cap-drop=all ) # drop all capabilities
flags+=( --network=none ) # no network needed
flags+=( -e TERM="$TERM" ) # pass $TERM
flags+=( -ti -e TERM="$TERM" ) # allocate an interactive pseudo-tty and pass $TERM
if [[ 1 == 1 ]]; then
# run as user upx 2000:2000
flags+=( --user 2000 )
@@ -21,8 +21,10 @@ if [[ 1 == 1 ]]; then
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+=( -v "${argv0dir}/../../..:/home/upx/src/upx" )
flags+=( -w /home/upx/src/upx ) # set working directory
flags+=( --tmpfs /home/upx/.cache:rw,exec ) # mount a writeable tmpfs
flags+=( --tmpfs /home/upx/.local:rw,exec ) # mount a writeable tmpfs
else
# run as user root 0:0
# ONLY FOR DEBUGGING THE IMAGE
@@ -30,7 +32,11 @@ else
flags+=( --user 0 )
fi
podman run "${flags[@]}" "$image" bash -l
if [[ $# == 0 ]]; then
podman run "${flags[@]}" "$image" bash -l
else
podman run "${flags[@]}" "$image" "$@"
fi
# now we can rebuild the UPX stubs:
# cd /home/upx/src/upx/src/stub
+65
View File
@@ -0,0 +1,65 @@
FROM docker.io/library/ubuntu:22.04
ENV UPX_CONTAINER_IMAGE_NAME=upx-stubtools-20221212-v6
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 bash bash-completion ca-certificates dash git less libmpc3 libncurses5 \
make ncurses-term perl-base python2-minimal time 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 busybox bzip2 cabextract ccache chrpath cmake cpio curl elfutils fd-find file fzf \
g++ gawk gdb gojq ht htop hyperfine jq libzstd-dev lsb-release lz4 lzip lzop \
mksh moreutils ninja-build p7zip parallel patch patchelf pax-utils paxctl \
python3 python3-pyasn1 python3-pycryptodome python3-zstd \
re2c ripgrep rsync screen universal-ctags unzip vim yash zip zlib1g-dev zsh zstd \
# extra packages for compiling with "gcc -m32" and and "gcc -mx32":
g++-multilib gcc-multilib \
&& true
# manually unpack and install compat libs from Ubuntu-16.04; REQUIRED
RUN cd /root \
&& aria2c --checksum=sha-256=de22baf3dd851a10e16fbf66a243e70149ca46e06b2939fdc79429196cefc090 \
'https://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 4.1.0 4.2.0; 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 4.1.0 4.2.0; 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:upx 2000:2000
RUN useradd upx -U --uid 2000 --shell /bin/bash -m \
&& cd /home/upx && chmod 00700 . \
# prepare ~/.cache and ~/.local for possible tmpfs mounts
&& mkdir -p .cache/tmp .local/bin src/upx \
&& for d in ccache fontconfig go-build mesa_shader_cache tmp wine zig; do mkdir -p .cache/$d; done \
&& for d in bin include lib share state; do mkdir -p .local/$d; done \
&& ln -s .cache/wine .wine && ln -s .cache/tmp tmp \
&& ln -s /usr/local/bin/bin-upx-20221212 .local/bin/bin-upx \
&& chown -R upx:upx . \
&& true
USER upx
+657
View File
@@ -0,0 +1,657 @@
Packages:
+++-===========================-=======================================-============-================================================================================
Desired=Unknown/Install/Remove/Purge/Hold
ii 7zip 21.07+dfsg-4 amd64 7-Zip file archiver with a high compression ratio
ii adduser 3.118ubuntu5 all add and remove users and groups
ii apt 2.4.10 amd64 commandline package manager
ii aria2 1.36.0-1 amd64 High speed download utility
ii base-files 12ubuntu4.4 amd64 Debian base system miscellaneous files
ii base-passwd 3.5.52build1 amd64 Debian base system master password and group files
ii bash 5.1-6ubuntu1 amd64 GNU Bourne Again SHell
ii bash-completion 1:2.11-5ubuntu1 all programmable completion for the bash shell
ii bfs 2.3.1-1 amd64 Breadth-first version of find(1)
ii binutils 2.38-4ubuntu2.3 amd64 GNU assembler, linker and binary utilities
ii binutils-common:amd64 2.38-4ubuntu2.3 amd64 Common files for the GNU assembler, linker and binary utilities
ii binutils-x86-64-linux-gnu 2.38-4ubuntu2.3 amd64 GNU binary utilities, for x86-64-linux-gnu target
ii bsdutils 1:2.37.2-4ubuntu3 amd64 basic utilities from 4.4BSD-Lite
ii busybox 1:1.30.1-7ubuntu3 amd64 Tiny utilities for small and embedded systems
ii bzip2 1.0.8-5build1 amd64 high-quality block-sorting file compressor - utilities
ii ca-certificates 20230311ubuntu0.22.04.1 all Common CA certificates
ii cabextract 1.9-3 amd64 Microsoft Cabinet file unpacker
ii ccache 4.5.1-1 amd64 Compiler cache for fast recompilation of C/C++ code
ii chrpath 0.16-2 amd64 Tool to edit the rpath in ELF binaries
ii cmake 3.22.1-1ubuntu1.22.04.1 amd64 cross-platform, open-source make system
ii cmake-data 3.22.1-1ubuntu1.22.04.1 all CMake data files (modules, templates and documentation)
ii coreutils 8.32-4.1ubuntu1 amd64 GNU core utilities
ii cpio 2.13+dfsg-7 amd64 GNU cpio -- a program to manage archives of files
ii cpp 4:11.2.0-1ubuntu1 amd64 GNU C preprocessor (cpp)
ii cpp-11 11.4.0-1ubuntu1~22.04 amd64 GNU C preprocessor
ii curl 7.81.0-1ubuntu1.14 amd64 command line tool for transferring data with URL syntax
ii dash 0.5.11+git20210903+057cd650a4ed-3build1 amd64 POSIX-compliant shell
ii debconf 1.5.79ubuntu1 all Debian configuration management system
ii debianutils 5.5-1ubuntu2 amd64 Miscellaneous utilities specific to Debian
ii dh-elpa-helper 2.0.9ubuntu1 all helper package for emacs lisp extensions
ii diffutils 1:3.8-0ubuntu2 amd64 File comparison utilities
ii distro-info-data 0.52ubuntu0.4 all information about the distributions' releases (data files)
ii dpkg 1.21.1ubuntu2.2 amd64 Debian package management system
ii e2fsprogs 1.46.5-2ubuntu1.1 amd64 ext2/ext3/ext4 file system utilities
ii elfutils 0.186-1build1 amd64 collection of utilities to handle ELF objects
ii emacsen-common 3.0.4 all Common facilities for all emacsen
ii fd-find 8.3.1-1ubuntu0.1 amd64 Simple, fast and user-friendly alternative to find
ii file 1:5.41-3ubuntu0.1 amd64 Recognize the type of data in a file using "magic" numbers
ii findutils 4.8.0-1ubuntu3 amd64 utilities for finding files--find, xargs
ii fzf 0.29.0-1 amd64 general-purpose command-line fuzzy finder
ii g++ 4:11.2.0-1ubuntu1 amd64 GNU C++ compiler
ii g++-11 11.4.0-1ubuntu1~22.04 amd64 GNU C++ compiler
ii g++-11-multilib 11.4.0-1ubuntu1~22.04 amd64 GNU C++ compiler (multilib support)
ii g++-multilib 4:11.2.0-1ubuntu1 amd64 GNU C++ compiler (multilib files)
ii gawk 1:5.1.0-1ubuntu0.1 amd64 GNU awk, a pattern scanning and processing language
ii gcc 4:11.2.0-1ubuntu1 amd64 GNU C compiler
ii gcc-11 11.4.0-1ubuntu1~22.04 amd64 GNU C compiler
ii gcc-11-base:amd64 11.4.0-1ubuntu1~22.04 amd64 GCC, the GNU Compiler Collection (base package)
ii gcc-11-multilib 11.4.0-1ubuntu1~22.04 amd64 GNU C compiler (multilib support)
ii gcc-12-base:amd64 12.3.0-1ubuntu1~22.04 amd64 GCC, the GNU Compiler Collection (base package)
ii gcc-12-base:i386 12.3.0-1ubuntu1~22.04 i386 GCC, the GNU Compiler Collection (base package)
ii gcc-multilib 4:11.2.0-1ubuntu1 amd64 GNU C compiler (multilib files)
ii gdb 12.1-0ubuntu1~22.04 amd64 GNU Debugger
ii git 1:2.34.1-1ubuntu1.10 amd64 fast, scalable, distributed revision control system
ii git-man 1:2.34.1-1ubuntu1.10 all fast, scalable, distributed revision control system (manual pages)
ii gojq 0.12.6-1 amd64 pure Go implementation of jq (program)
ii gpgv 2.2.27-3ubuntu2.1 amd64 GNU privacy guard - signature verification tool
ii grep 3.7-1build1 amd64 GNU grep, egrep and fgrep
ii gzip 1.10-4ubuntu4.1 amd64 GNU compression utilities
ii hostname 3.23ubuntu2 amd64 utility to set/show the host name or domain name
ii ht 2.1.0+repack1-5 amd64 Viewer/editor/analyser (mostly) for executables
ii htop 3.0.5-7build2 amd64 interactive processes viewer
ii hyperfine 1.12.0-3ubuntu0.1 amd64 Command-line benchmarking tool
ii init-system-helpers 1.62 all helper tools for all init systems
ii jq 1.6-2.1ubuntu3 amd64 lightweight and flexible command-line JSON processor
ii less 590-1ubuntu0.22.04.1 amd64 pager program similar to more
ii lib32asan6 11.4.0-1ubuntu1~22.04 amd64 AddressSanitizer -- a fast memory error detector (32bit)
ii lib32atomic1 12.3.0-1ubuntu1~22.04 amd64 support library providing __atomic built-in functions (32bit)
ii lib32gcc-11-dev 11.4.0-1ubuntu1~22.04 amd64 GCC support library (32 bit development files)
ii lib32gcc-s1 12.3.0-1ubuntu1~22.04 amd64 GCC support library (32 bit Version)
ii lib32gomp1 12.3.0-1ubuntu1~22.04 amd64 GCC OpenMP (GOMP) support library (32bit)
ii lib32itm1 12.3.0-1ubuntu1~22.04 amd64 GNU Transactional Memory Library (32bit)
ii lib32quadmath0 12.3.0-1ubuntu1~22.04 amd64 GCC Quad-Precision Math Library (32bit)
ii lib32stdc++-11-dev 11.4.0-1ubuntu1~22.04 amd64 GNU Standard C++ Library v3 (development files)
ii lib32stdc++6 12.3.0-1ubuntu1~22.04 amd64 GNU Standard C++ Library v3 (32 bit Version)
ii lib32ubsan1 12.3.0-1ubuntu1~22.04 amd64 UBSan -- undefined behaviour sanitizer (32bit)
ii libacl1:amd64 2.3.1-1 amd64 access control list - shared library
ii libapt-pkg6.0:amd64 2.4.10 amd64 package management runtime library
ii libarchive13:amd64 3.6.0-1ubuntu1 amd64 Multi-format archive and compression library (shared library)
ii libaria2-0:amd64 1.36.0-1 amd64 C++ library interface to aria2
ii libasan6:amd64 11.4.0-1ubuntu1~22.04 amd64 AddressSanitizer -- a fast memory error detector
ii libasm1:amd64 0.186-1build1 amd64 library with a programmable assembler interface
ii libatomic1:amd64 12.3.0-1ubuntu1~22.04 amd64 support library providing __atomic built-in functions
ii libattr1:amd64 1:2.5.1-1build1 amd64 extended attribute handling - shared library
ii libaudit-common 1:3.0.7-1build1 all Dynamic library for security auditing - common files
ii libaudit1:amd64 1:3.0.7-1build1 amd64 Dynamic library for security auditing
ii libbabeltrace1:amd64 1.5.8-2build1 amd64 Babeltrace conversion libraries
ii libbinutils:amd64 2.38-4ubuntu2.3 amd64 GNU binary utilities (private shared library)
ii libblkid1:amd64 2.37.2-4ubuntu3 amd64 block device ID library
ii libboost-regex1.74.0:amd64 1.74.0-14ubuntu3 amd64 regular expression library for C++
ii libbrotli1:amd64 1.0.9-2build6 amd64 library implementing brotli encoder and decoder (shared libraries)
ii libbsd0:amd64 0.11.5-1 amd64 utility functions from BSD systems - shared library
ii libbz2-1.0:amd64 1.0.8-5build1 amd64 high-quality block-sorting file compressor library - runtime
ii libc-ares2:amd64 1.18.1-1ubuntu0.22.04.2 amd64 asynchronous name resolver
ii libc-bin 2.35-0ubuntu3.4 amd64 GNU C Library: Binaries
ii libc-dev-bin 2.35-0ubuntu3.4 amd64 GNU C Library: Development binaries
ii libc6-dev-i386 2.35-0ubuntu3.4 amd64 GNU C Library: 32-bit development libraries for AMD64
ii libc6-dev-x32 2.35-0ubuntu3.4 amd64 GNU C Library: X32 ABI Development Libraries for AMD64
ii libc6-dev:amd64 2.35-0ubuntu3.4 amd64 GNU C Library: Development Libraries and Header Files
ii libc6-i386 2.35-0ubuntu3.4 amd64 GNU C Library: 32-bit shared libraries for AMD64
ii libc6-x32 2.35-0ubuntu3.4 amd64 GNU C Library: X32 ABI Shared libraries for AMD64
ii libc6:amd64 2.35-0ubuntu3.4 amd64 GNU C Library: Shared libraries
ii libc6:i386 2.35-0ubuntu3.4 i386 GNU C Library: Shared libraries
ii libcap-ng0:amd64 0.7.9-2.2build3 amd64 An alternate POSIX capabilities library
ii libcap2:amd64 1:2.44-1ubuntu0.22.04.1 amd64 POSIX 1003.1e capabilities (library)
ii libcc1-0:amd64 12.3.0-1ubuntu1~22.04 amd64 GCC cc1 plugin for GDB
ii libcom-err2:amd64 1.46.5-2ubuntu1.1 amd64 common error description library
ii libcrypt-dev:amd64 1:4.4.27-1 amd64 libcrypt development files
ii libcrypt1:amd64 1:4.4.27-1 amd64 libcrypt shared library
ii libcrypt1:i386 1:4.4.27-1 i386 libcrypt shared library
ii libctf-nobfd0:amd64 2.38-4ubuntu2.3 amd64 Compact C Type Format library (runtime, no BFD dependency)
ii libctf0:amd64 2.38-4ubuntu2.3 amd64 Compact C Type Format library (runtime, BFD dependency)
ii libcurl3-gnutls:amd64 7.81.0-1ubuntu1.14 amd64 easy-to-use client-side URL transfer library (GnuTLS flavour)
ii libcurl4:amd64 7.81.0-1ubuntu1.14 amd64 easy-to-use client-side URL transfer library (OpenSSL flavour)
ii libdb5.3:amd64 5.3.28+dfsg1-0.8ubuntu3 amd64 Berkeley v5.3 Database Libraries [runtime]
ii libdebconfclient0:amd64 0.261ubuntu1 amd64 Debian Configuration Management System (C-implementation library)
ii libdebuginfod-common 0.186-1build1 all configuration to enable the Debian debug info server
ii libdebuginfod1:amd64 0.186-1build1 amd64 library to interact with debuginfod (development files)
ii libdw1:amd64 0.186-1build1 amd64 library that provides access to the DWARF debug information
ii libelf1:amd64 0.186-1build1 amd64 library to read and write ELF files
ii liberror-perl 0.17029-1 all Perl module for error/exception handling in an OO-ish way
ii libexpat1:amd64 2.4.7-1ubuntu0.2 amd64 XML parsing C library - runtime library
ii libext2fs2:amd64 1.46.5-2ubuntu1.1 amd64 ext2/ext3/ext4 file system libraries
ii libffi8:amd64 3.4.2-4 amd64 Foreign Function Interface library runtime
ii libgcc-11-dev:amd64 11.4.0-1ubuntu1~22.04 amd64 GCC support library (development files)
ii libgcc-s1:amd64 12.3.0-1ubuntu1~22.04 amd64 GCC support library
ii libgcc-s1:i386 12.3.0-1ubuntu1~22.04 i386 GCC support library
ii libgcrypt20:amd64 1.9.4-3ubuntu3 amd64 LGPL Crypto library - runtime library
ii libgdbm-compat4:amd64 1.23-1 amd64 GNU dbm database routines (legacy support runtime version)
ii libgdbm6:amd64 1.23-1 amd64 GNU dbm database routines (runtime version)
ii libglib2.0-0:amd64 2.72.4-0ubuntu2.2 amd64 GLib library of C routines
ii libgmp10:amd64 2:6.2.1+dfsg-3ubuntu1 amd64 Multiprecision arithmetic library
ii libgnutls30:amd64 3.7.3-4ubuntu1.2 amd64 GNU TLS library - main runtime library
ii libgomp1:amd64 12.3.0-1ubuntu1~22.04 amd64 GCC OpenMP (GOMP) support library
ii libgpg-error0:amd64 1.43-3 amd64 GnuPG development runtime library
ii libgpm2:amd64 1.20.7-10build1 amd64 General Purpose Mouse - shared library
ii libgssapi-krb5-2:amd64 1.19.2-2ubuntu0.2 amd64 MIT Kerberos runtime libraries - krb5 GSS-API Mechanism
ii libhiredis0.14:amd64 0.14.1-2 amd64 minimalistic C client library for Redis
ii libhogweed6:amd64 3.7.3-1build2 amd64 low level cryptographic library (public-key cryptos)
ii libicu70:amd64 70.1-2 amd64 International Components for Unicode
ii libidn2-0:amd64 2.3.2-2build1 amd64 Internationalized domain names (IDNA2008/TR46) library
ii libio-pty-perl 1:1.15-2build2 amd64 Perl module for pseudo tty IO
ii libipc-run-perl 20200505.0-1 all Perl module for running processes
ii libipt2 2.0.5-1 amd64 Intel Processor Trace Decoder Library
ii libisl23:amd64 0.24-2build1 amd64 manipulating sets and relations of integer points bounded by linear constraints
ii libitm1:amd64 12.3.0-1ubuntu1~22.04 amd64 GNU Transactional Memory Library
ii libjansson4:amd64 2.13.1-1.1build3 amd64 C library for encoding, decoding and manipulating JSON data
ii libjq1:amd64 1.6-2.1ubuntu3 amd64 lightweight and flexible command-line JSON processor - shared library
ii libjsoncpp25:amd64 1.9.5-3 amd64 library for reading and writing JSON for C++
ii libk5crypto3:amd64 1.19.2-2ubuntu0.2 amd64 MIT Kerberos runtime libraries - Crypto Library
ii libkeyutils1:amd64 1.6.1-2ubuntu3 amd64 Linux Key Management Utilities (library)
ii libkrb5-3:amd64 1.19.2-2ubuntu0.2 amd64 MIT Kerberos runtime libraries
ii libkrb5support0:amd64 1.19.2-2ubuntu0.2 amd64 MIT Kerberos runtime libraries - Support library
ii libldap-2.5-0:amd64 2.5.16+dfsg-0ubuntu0.22.04.1 amd64 OpenLDAP libraries
ii liblsan0:amd64 12.3.0-1ubuntu1~22.04 amd64 LeakSanitizer -- a memory leak detector (runtime)
ii liblz4-1:amd64 1.9.3-2build2 amd64 Fast LZ compression algorithm library - runtime
ii liblzma5:amd64 5.2.5-2ubuntu1 amd64 XZ-format compression library
ii liblzo2-2:amd64 2.10-2build3 amd64 data compression library
ii libmagic-mgc 1:5.41-3ubuntu0.1 amd64 File type determination library using "magic" numbers (compiled magic file)
ii libmagic1:amd64 1:5.41-3ubuntu0.1 amd64 Recognize the type of data in a file using "magic" numbers - library
ii libmd0:amd64 1.0.4-1build1 amd64 message digest functions from BSD systems - shared library
ii libmount1:amd64 2.37.2-4ubuntu3 amd64 device mounting library
ii libmpc3:amd64 1.2.1-2build1 amd64 multiple precision complex floating-point library
ii libmpdec3:amd64 2.5.1-2build2 amd64 library for decimal floating point arithmetic (runtime library)
ii libmpfr6:amd64 4.1.0-3build3 amd64 multiple precision floating-point computation
ii libmspack0:amd64 0.10.1-2build2 amd64 library for Microsoft compression formats (shared library)
ii libncurses5:amd64 6.3-2ubuntu0.1 amd64 shared libraries for terminal handling (legacy version)
ii libncurses6:amd64 6.3-2ubuntu0.1 amd64 shared libraries for terminal handling
ii libncursesw6:amd64 6.3-2ubuntu0.1 amd64 shared libraries for terminal handling (wide character support)
ii libnettle8:amd64 3.7.3-1build2 amd64 low level cryptographic library (symmetric and one-way cryptos)
ii libnghttp2-14:amd64 1.43.0-1build3 amd64 library implementing HTTP/2 protocol (shared library)
ii libnl-3-200:amd64 3.5.0-0.1 amd64 library for dealing with netlink sockets
ii libnl-genl-3-200:amd64 3.5.0-0.1 amd64 library for dealing with netlink sockets - generic netlink
ii libnsl-dev:amd64 1.3.0-2build2 amd64 libnsl development files
ii libnsl2:amd64 1.3.0-2build2 amd64 Public client interface for NIS(YP) and NIS+
ii libonig5:amd64 6.9.7.1-2build1 amd64 regular expressions library
ii libp11-kit0:amd64 0.24.0-6build1 amd64 library for loading and coordinating access to PKCS#11 modules - runtime
ii libpam-modules-bin 1.4.0-11ubuntu2.3 amd64 Pluggable Authentication Modules for PAM - helper binaries
ii libpam-modules:amd64 1.4.0-11ubuntu2.3 amd64 Pluggable Authentication Modules for PAM
ii libpam-runtime 1.4.0-11ubuntu2.3 all Runtime support for the PAM library
ii libpam0g:amd64 1.4.0-11ubuntu2.3 amd64 Pluggable Authentication Modules library
ii libpcre2-8-0:amd64 10.39-3ubuntu0.1 amd64 New Perl Compatible Regular Expression Library- 8 bit runtime files
ii libpcre3:amd64 2:8.39-13ubuntu0.22.04.1 amd64 Old Perl 5 Compatible Regular Expression Library - runtime files
ii libperl5.34:amd64 5.34.0-3ubuntu1.2 amd64 shared Perl library
ii libpopt0:amd64 1.18-3build1 amd64 lib for parsing cmdline parameters
ii libprocps8:amd64 2:3.3.17-6ubuntu2 amd64 library for accessing process information from /proc
ii libpsl5:amd64 0.21.0-1.2build2 amd64 Library for Public Suffix List (shared libraries)
ii libpython2.7-minimal:amd64 2.7.18-13ubuntu1.1 amd64 Minimal subset of the Python language (version 2.7)
ii libpython3-stdlib:amd64 3.10.6-1~22.04 amd64 interactive high-level object-oriented language (default python3 version)
ii libpython3.10-minimal:amd64 3.10.12-1~22.04.2 amd64 Minimal subset of the Python language (version 3.10)
ii libpython3.10-stdlib:amd64 3.10.12-1~22.04.2 amd64 Interactive high-level object-oriented language (standard library, version 3.10)
ii libpython3.10:amd64 3.10.12-1~22.04.2 amd64 Shared Python runtime library (version 3.10)
ii libquadmath0:amd64 12.3.0-1ubuntu1~22.04 amd64 GCC Quad-Precision Math Library
ii libreadline8:amd64 8.1.2-1 amd64 GNU readline and history libraries, run-time libraries
ii librhash0:amd64 1.4.2-1ubuntu1 amd64 shared library for hash functions computing
ii librtmp1:amd64 2.4+20151223.gitfa8646d.1-2build4 amd64 toolkit for RTMP streams (shared library)
ii libsasl2-2:amd64 2.1.27+dfsg2-3ubuntu1.2 amd64 Cyrus SASL - authentication abstraction library
ii libsasl2-modules-db:amd64 2.1.27+dfsg2-3ubuntu1.2 amd64 Cyrus SASL - pluggable authentication modules (DB)
ii libseccomp2:amd64 2.5.3-2ubuntu2 amd64 high level interface to Linux seccomp filter
ii libselinux1:amd64 3.3-1build2 amd64 SELinux runtime shared libraries
ii libsemanage-common 3.3-1build2 all Common files for SELinux policy management libraries
ii libsemanage2:amd64 3.3-1build2 amd64 SELinux policy management library
ii libsensors-config 1:3.6.0-7ubuntu1 all lm-sensors configuration files
ii libsensors5:amd64 1:3.6.0-7ubuntu1 amd64 library to read temperature/voltage/fan sensors
ii libsepol2:amd64 3.3-1build1 amd64 SELinux library for manipulating binary security policies
ii libsigsegv2:amd64 2.13-1ubuntu3 amd64 Library for handling page faults in a portable way
ii libsmartcols1:amd64 2.37.2-4ubuntu3 amd64 smart column output alignment library
ii libsodium23:amd64 1.0.18-1build2 amd64 Network communication, cryptography and signaturing library
ii libsource-highlight-common 3.1.9-4.1build2 all architecture-independent files for source highlighting library
ii libsource-highlight4v5 3.1.9-4.1build2 amd64 source highlighting library
ii libsqlite3-0:amd64 3.37.2-2ubuntu0.1 amd64 SQLite 3 shared library
ii libss2:amd64 1.46.5-2ubuntu1.1 amd64 command-line interface parsing library
ii libssh-4:amd64 0.9.6-2ubuntu0.22.04.1 amd64 tiny C SSH library (OpenSSL flavor)
ii libssh2-1:amd64 1.10.0-3 amd64 SSH2 client-side library
ii libssl3:amd64 3.0.2-0ubuntu1.10 amd64 Secure Sockets Layer toolkit - shared libraries
ii libstdc++-11-dev:amd64 11.4.0-1ubuntu1~22.04 amd64 GNU Standard C++ Library v3 (development files)
ii libstdc++6:amd64 12.3.0-1ubuntu1~22.04 amd64 GNU Standard C++ Library v3
ii libsystemd0:amd64 249.11-0ubuntu3.10 amd64 systemd utility library
ii libtasn1-6:amd64 4.18.0-4build1 amd64 Manage ASN.1 structures (runtime)
ii libtime-duration-perl 1.21-1 all module for rounded or exact English expression of durations
ii libtimedate-perl 2.3300-2 all collection of modules to manipulate date/time information
ii libtinfo5:amd64 6.3-2ubuntu0.1 amd64 shared low-level terminfo library (legacy version)
ii libtinfo6:amd64 6.3-2ubuntu0.1 amd64 shared low-level terminfo library for terminal handling
ii libtirpc-common 1.3.2-2ubuntu0.1 all transport-independent RPC library - common files
ii libtirpc-dev:amd64 1.3.2-2ubuntu0.1 amd64 transport-independent RPC library - development files
ii libtirpc3:amd64 1.3.2-2ubuntu0.1 amd64 transport-independent RPC library
ii libtsan0:amd64 11.4.0-1ubuntu1~22.04 amd64 ThreadSanitizer -- a Valgrind-based detector of data races (runtime)
ii libubsan1:amd64 12.3.0-1ubuntu1~22.04 amd64 UBSan -- undefined behaviour sanitizer (runtime)
ii libudev1:amd64 249.11-0ubuntu3.10 amd64 libudev shared library
ii libunistring2:amd64 1.0-1 amd64 Unicode string library for C
ii libutempter0:amd64 1.2.1-2build2 amd64 privileged helper for utmp/wtmp updates (runtime)
ii libuuid1:amd64 2.37.2-4ubuntu3 amd64 Universally Unique ID library
ii libuv1:amd64 1.43.0-1 amd64 asynchronous event notification library - runtime library
ii libx11-6:amd64 2:1.7.5-1ubuntu0.3 amd64 X11 client-side library
ii libx11-data 2:1.7.5-1ubuntu0.3 all X11 client-side library
ii libx32asan6 11.4.0-1ubuntu1~22.04 amd64 AddressSanitizer -- a fast memory error detector (x32)
ii libx32atomic1 12.3.0-1ubuntu1~22.04 amd64 support library providing __atomic built-in functions (x32)
ii libx32gcc-11-dev 11.4.0-1ubuntu1~22.04 amd64 GCC support library (x32 development files)
ii libx32gcc-s1 12.3.0-1ubuntu1~22.04 amd64 GCC support library (x32)
ii libx32gomp1 12.3.0-1ubuntu1~22.04 amd64 GCC OpenMP (GOMP) support library (x32)
ii libx32itm1 12.3.0-1ubuntu1~22.04 amd64 GNU Transactional Memory Library (x32)
ii libx32quadmath0 12.3.0-1ubuntu1~22.04 amd64 GCC Quad-Precision Math Library (x32)
ii libx32stdc++-11-dev 11.4.0-1ubuntu1~22.04 amd64 GNU Standard C++ Library v3 (development files)
ii libx32stdc++6 12.3.0-1ubuntu1~22.04 amd64 GNU Standard C++ Library v3 (x32)
ii libx32ubsan1 12.3.0-1ubuntu1~22.04 amd64 UBSan -- undefined behaviour sanitizer (x32)
ii libxau6:amd64 1:1.0.9-1build5 amd64 X11 authorisation library
ii libxcb1:amd64 1.14-3ubuntu3 amd64 X C Binding
ii libxdmcp6:amd64 1:1.1.3-0ubuntu5 amd64 X11 Display Manager Control Protocol library
ii libxml2:amd64 2.9.13+dfsg-1ubuntu0.3 amd64 GNOME XML library
ii libxxhash0:amd64 0.8.1-1 amd64 shared library for xxhash
ii libyaml-0-2:amd64 0.2.2-1build2 amd64 Fast YAML 1.1 parser and emitter library
ii libzstd-dev:amd64 1.4.8+dfsg-3build1 amd64 fast lossless compression algorithm -- development files
ii libzstd1:amd64 1.4.8+dfsg-3build1 amd64 fast lossless compression algorithm
ii linux-libc-dev:amd64 5.15.0-87.97 amd64 Linux Kernel Headers for development
ii login 1:4.8.1-2ubuntu2.1 amd64 system login tools
ii logsave 1.46.5-2ubuntu1.1 amd64 save the output of a command in a log file
ii lsb-base 11.1.0ubuntu4 all Linux Standard Base init script functionality
ii lsb-release 11.1.0ubuntu4 all Linux Standard Base version reporting utility
ii lz4 1.9.3-2build2 amd64 Fast LZ compression algorithm library - tool
ii lzip 1.23-1 amd64 lossless data compressor based on the LZMA algorithm
ii lzop 1.04-2build2 amd64 fast compression program
ii make 4.3-4.1build1 amd64 utility for directing compilation
ii mawk 1.3.4.20200120-3 amd64 Pattern scanning and text processing language
ii media-types 7.0.0 all List of standard media types and their usual file extension
ii mksh 59c-16 amd64 MirBSD Korn Shell
ii moreutils 0.66-1 amd64 additional Unix utilities
ii mount 2.37.2-4ubuntu3 amd64 tools for mounting and manipulating filesystems
ii ncurses-base 6.3-2ubuntu0.1 all basic terminal type definitions
ii ncurses-bin 6.3-2ubuntu0.1 amd64 terminal-related programs and man pages
ii ncurses-term 6.3-2ubuntu0.1 all additional terminal type definitions
ii ninja-build 1.10.1-1 amd64 small build system closest in spirit to Make
ii openssl 3.0.2-0ubuntu1.10 amd64 Secure Sockets Layer toolkit - cryptographic utility
ii p7zip 16.02+dfsg-8 amd64 7zr file archiver with high compression ratio
ii parallel 20210822+ds-2 all build and execute command lines from standard input in parallel
ii passwd 1:4.8.1-2ubuntu2.1 amd64 change and administer password and group data
ii patch 2.7.6-7build2 amd64 Apply a diff file to an original
ii patchelf 0.14.3-1 amd64 modify properties of ELF executables
ii pax-utils 1.2.9-1 amd64 Security-focused ELF files checking tool
ii paxctl 0.9-1build1 amd64 new PaX control program for using the PT_PAX_FLAGS marking
ii perl 5.34.0-3ubuntu1.2 amd64 Larry Wall's Practical Extraction and Report Language
ii perl-base 5.34.0-3ubuntu1.2 amd64 minimal Perl system
ii perl-modules-5.34 5.34.0-3ubuntu1.2 all Core Perl modules
ii procps 2:3.3.17-6ubuntu2 amd64 /proc file system utilities
ii python2-minimal 2.7.18-3 amd64 minimal subset of the Python2 language
ii python2.7-minimal 2.7.18-13ubuntu1.1 amd64 Minimal subset of the Python language (version 2.7)
ii python3 3.10.6-1~22.04 amd64 interactive high-level object-oriented language (default python3 version)
ii python3-minimal 3.10.6-1~22.04 amd64 minimal subset of the Python language (default python3 version)
ii python3-pyasn1 0.4.8-1 all ASN.1 library for Python (Python 3 module)
ii python3-pycryptodome 3.11.0+dfsg1-3build1 amd64 cryptographic Python library (Python 3)
ii python3-zstd 1.5.0.2-1build1 amd64 python bindings to Yann Collet ZSTD compression library
ii python3.10 3.10.12-1~22.04.2 amd64 Interactive high-level object-oriented language (version 3.10)
ii python3.10-minimal 3.10.12-1~22.04.2 amd64 Minimal subset of the Python language (version 3.10)
ii re2c 3.0-1 amd64 lexer generator for C, C++, Go and Rust
ii readline-common 8.1.2-1 all GNU readline and history libraries, common files
ii ripgrep 13.0.0-2ubuntu0.1 amd64 Recursively searches directories for a regex pattern
ii rpcsvc-proto 1.4.2-0ubuntu6 amd64 RPC protocol compiler and definitions
ii rsync 3.2.7-0ubuntu0.22.04.2 amd64 fast, versatile, remote (and local) file-copying tool
ii screen 4.9.0-1 amd64 terminal multiplexer with VT100/ANSI terminal emulation
ii sed 4.8-1ubuntu2 amd64 GNU stream editor for filtering/transforming text
ii sensible-utils 0.0.17 all Utilities for sensible alternative selection
ii sysstat 12.5.2-2ubuntu0.2 amd64 system performance tools for Linux
ii sysvinit-utils 3.01-1ubuntu1 amd64 System-V-like utilities
ii tar 1.34+dfsg-1ubuntu0.1.22.04.1 amd64 GNU version of the tar archiving utility
ii time 1.9-0.1build2 amd64 GNU time program for measuring CPU resource usage
ii ubuntu-keyring 2021.03.26 all GnuPG keys of the Ubuntu archive
ii ucf 3.0043 all Update Configuration File(s): preserve user changes to config files
ii universal-ctags 5.9.20210829.0-1 amd64 build tag file indexes of source code definitions
ii unzip 6.0-26ubuntu3.1 amd64 De-archiver for .zip files
ii usrmerge 25ubuntu2 all Convert the system to the merged /usr directories scheme
ii util-linux 2.37.2-4ubuntu3 amd64 miscellaneous system utilities
ii vim 2:8.2.3995-1ubuntu2.12 amd64 Vi IMproved - enhanced vi editor
ii vim-common 2:8.2.3995-1ubuntu2.12 all Vi IMproved - Common files
ii vim-runtime 2:8.2.3995-1ubuntu2.12 all Vi IMproved - Runtime files
ii wget 1.21.2-2ubuntu1 amd64 retrieves files from the web
ii xxd 2:8.2.3995-1ubuntu2.12 amd64 tool to make (or reverse) a hex dump
ii xz-utils 5.2.5-2ubuntu1 amd64 XZ-format compression utilities
ii yash 2.51-1 amd64 yet another shell
ii zip 3.0-12build2 amd64 Archiver for .zip files
ii zlib1g-dev:amd64 1:1.2.11.dfsg-2ubuntu9.2 amd64 compression library - development
ii zlib1g:amd64 1:1.2.11.dfsg-2ubuntu9.2 amd64 compression library - runtime
ii zlib1g:i386 1:1.2.11.dfsg-2ubuntu9.2 i386 compression library - runtime
ii zsh 5.8.1-1 amd64 shell with lots of features
ii zsh-common 5.8.1-1 all architecture independent files for Zsh
ii zstd 1.4.8+dfsg-3build1 amd64 fast lossless compression algorithm -- CLI tool
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
Packages sorted by Installed-Size:
754072 ===== TOTAL (324 packages)
52747 gcc-11 amd64
34444 libicu70 amd64
32781 vim-runtime all
28891 g++-11 amd64
28441 libperl5.34 amd64
26284 cpp-11 amd64
20742 cmake amd64
18759 libstdc++-11-dev amd64
18468 git amd64
17671 perl-modules-5.34 all
15293 zsh-common all
13895 libgcc-11-dev amd64
13592 libc6 amd64
13037 libc6-dev amd64
12561 libc6-x32 amd64
12479 libc6 i386
12200 libc6-i386 amd64
11311 gdb amd64
10877 lib32stdc++-11-dev amd64
10439 binutils-x86-64-linux-gnu amd64
10390 libx32stdc++-11-dev amd64
9866 cmake-data all
8248 libc6-dev-x32 amd64
8119 libpython3.10-stdlib amd64
7948 lib32gcc-11-dev amd64
7730 perl-base amd64
7518 libasan6 amd64
7262 libc6-dev-i386 amd64
7255 libtsan0 amd64
7128 libmagic-mgc amd64
7112 coreutils amd64
6988 libx32gcc-11-dev amd64
6795 linux-libc-dev amd64
6733 dpkg amd64
6667 lib32asan6 amd64
6570 libx32asan6 amd64
5905 python3.10-minimal amd64
5824 libssl3 amd64
5768 libpython3.10 amd64
5103 libpython3.10-minimal amd64
4249 ncurses-term all
4156 apt amd64
4147 ripgrep amd64
4082 libglib2.0-0 amd64
3925 vim amd64
3643 python2.7-minimal amd64
3542 python3-pycryptodome amd64
3506 re2c amd64
3487 gojq amd64
3405 libmpfr6 amd64
3399 util-linux amd64
3347 libaria2-0 amd64
3181 libapt-pkg6.0 amd64
3013 libboost-regex1.74.0 amd64
2961 liblsan0 amd64
2943 parallel all
2801 elfutils amd64
2784 libpython2.7-minimal amd64
2776 libbinutils amd64
2755 libstdc++6 amd64
2676 libubsan1 amd64
2662 lib32stdc++6 amd64
2537 libc-bin amd64
2518 libx32ubsan1 amd64
2510 fd-find amd64
2499 lib32ubsan1 amd64
2468 zsh amd64
2450 libx32stdc++6 amd64
2428 fzf amd64
2396 7zip amd64
2325 passwd amd64
2284 libgnutls30 amd64
2191 ht amd64
2159 libisl23 amd64
2097 libxml2 amd64
2053 openssl amd64
2009 universal-ctags amd64
1958 git-man all
1864 bash amd64
1854 aria2 amd64
1750 libdb5.3 amd64
1746 libunistring2 amd64
1680 gawk amd64
1655 zstd amd64
1602 libsqlite3-0 amd64
1516 e2fsprogs amd64
1508 mksh amd64
1472 sysstat amd64
1464 bash-completion all
1445 hyperfine amd64
1430 libx11-data all
1429 yash amd64
1388 procps amd64
1387 libx11-6 amd64
1354 libgcrypt20 amd64
1343 ccache amd64
1328 libzstd-dev amd64
1292 libp11-kit0 amd64
1138 libpam-modules amd64
1052 libkrb5-3 amd64
1005 screen amd64
995 libsystemd0 amd64
990 p7zip amd64
984 wget amd64
960 tar amd64
888 login amd64
876 libarchive13 amd64
846 libzstd1 amd64
794 rsync amd64
791 busybox amd64
787 libcurl4 amd64
784 libbrotli1 amd64
771 libcurl3-gnutls amd64
743 python3-zstd amd64
735 libsepol2 amd64
729 libdw1 amd64
720 libtirpc-dev amd64
717 perl amd64
686 lib32quadmath0 amd64
683 libpcre3 amd64
646 ncurses-bin amd64
632 python3.10 amd64
621 libpcre2-8-0 amd64
620 findutils amd64
615 libonig5 amd64
610 libsource-highlight4v5 amd64
608 adduser all
592 zlib1g-dev amd64
574 libext2fs2 amd64
565 libldap-2.5-0 amd64
558 libtinfo6 amd64
544 libtinfo5 amd64
544 libgmp10 amd64
531 zip amd64
512 debconf all
504 binutils-common amd64
502 libbabeltrace1 amd64
496 grep amd64
486 libssh-4 amd64
461 libreadline8 amd64
455 libgssapi-krb5-2 amd64
443 curl amd64
433 libexpat1 amd64
424 diffutils amd64
422 libncursesw6 amd64
416 make amd64
402 libsodium23 amd64
394 base-files amd64
393 ncurses-base all
390 python3-pyasn1 all
390 ca-certificates all
389 mount amd64
382 libmount1 amd64
380 vim-common all
376 unzip amd64
372 xz-utils amd64
368 libssh2-1 amd64
356 libnettle8 amd64
350 ninja-build amd64
347 libudev1 amd64
347 libnsl-dev amd64
347 libjq1 amd64
336 libhogweed6 amd64
334 lib32gomp1 amd64
334 htop amd64
334 bsdutils amd64
329 libncurses6 amd64
328 sed amd64
324 gpgv amd64
324 cpio amd64
323 libblkid1 amd64
321 less amd64
320 libgomp1 amd64
320 libcrypt-dev amd64
318 libncurses5 amd64
312 libpam-runtime all
312 libctf-nobfd0 amd64
307 libsource-highlight-common all
306 libx32gomp1 amd64
300 libsemanage2 amd64
298 libc-dev-bin amd64
296 libquadmath0 amd64
295 libx32quadmath0 amd64
292 libk5crypto3 amd64
290 pax-utils amd64
290 liblzma5 amd64
278 xxd amd64
273 gcc-11-base amd64
272 gcc-12-base i386
272 gcc-12-base amd64
252 libuv1 amd64
252 libipc-run-perl all
252 libcrypt1 i386
250 libmpdec3 amd64
248 libpam-modules-bin amd64
245 rpcsvc-proto amd64
243 debianutils amd64
243 base-passwd amd64
240 moreutils amd64
240 gzip amd64
239 libctf0 amd64
235 libpam0g amd64
235 libjsoncpp25 amd64
232 ucf all
230 lz4 amd64
229 patch amd64
229 mawk amd64
229 libmagic1 amd64
225 libcrypt1 amd64
221 bfs amd64
220 libidn2-0 amd64
219 libtirpc3 amd64
219 librhash0 amd64
214 dash amd64
209 libsmartcols1 amd64
207 libselinux1 amd64
206 libxcb1 amd64
203 libnghttp2-14 amd64
200 usrmerge all
192 libelf1 amd64
189 libgpg-error0 amd64
182 patchelf amd64
180 libnl-3-200 amd64
171 zlib1g i386
170 libsasl2-2 amd64
167 libgcc-s1 i386
164 zlib1g amd64
164 libkrb5support0 amd64
163 lib32gcc-s1 amd64
161 lzip amd64
159 lzop amd64
159 liblzo2-2 amd64
156 libaudit1 amd64
145 libseccomp2 amd64
145 liblz4-1 amd64
144 libyaml-0-2 amd64
144 libcc1-0 amd64
141 librtmp1 amd64
140 libgcc-s1 amd64
136 libbsd0 amd64
135 libx32gcc-s1 amd64
134 libuuid1 amd64
133 libtasn1-6 amd64
133 init-system-helpers all
132 libipt2 amd64
131 libprocps8 amd64
126 time amd64
125 libmpc3 amd64
123 libtimedate-perl all
123 libnsl2 amd64
122 python3-minimal amd64
120 libpopt0 amd64
115 libitm1 amd64
114 bzip2 amd64
113 libss2 amd64
113 lib32itm1 amd64
112 libc-ares2 amd64
112 binutils amd64
110 libio-pty-perl amd64
105 python2-minimal amd64
105 libx32itm1 amd64
101 libcom-err2 amd64
100 libgdbm6 amd64
100 libbz2-1.0 amd64
100 jq amd64
97 media-types all
97 logsave amd64
97 libxxhash0 amd64
96 libsensors5 amd64
96 libmspack0 amd64
95 libpsl5 amd64
93 libsasl2-modules-db amd64
92 libhiredis0.14 amd64
91 libjansson4 amd64
90 python3 amd64
84 file amd64
83 sysvinit-utils amd64
82 cabextract amd64
80 readline-common all
79 libdebconfclient0 amd64
74 libasm1 amd64
71 libmd0 amd64
71 liberror-perl all
69 libffi8 amd64
67 libacl1 amd64
67 cpp amd64
66 lsb-release all
65 libgpm2 amd64
65 libdebuginfod1 amd64
65 libcap2 amd64
62 emacsen-common all
61 libnl-genl-3-200 amd64
59 sensible-utils all
58 lsb-base all
57 libattr1 amd64
51 libutempter0 amd64
51 hostname amd64
50 gcc amd64
49 libsigsegv2 amd64
47 libkeyutils1 amd64
45 libgdbm-compat4 amd64
45 libcap-ng0 amd64
45 libatomic1 amd64
43 libxdmcp6 amd64
43 libx32atomic1 amd64
42 libsensors-config all
41 ubuntu-keyring all
41 libdebuginfod-common all
39 libpython3-stdlib amd64
39 lib32atomic1 amd64
37 libsemanage-common all
37 chrpath amd64
35 libxau6 amd64
35 libtime-duration-perl all
32 libtirpc-common all
30 paxctl amd64
27 dh-elpa-helper all
23 libaudit-common all
20 distro-info-data all
16 g++ amd64
8 gcc-multilib amd64
6 gcc-11-multilib amd64
6 g++-multilib amd64
6 g++-11-multilib amd64
-58
View File
@@ -1,58 +0,0 @@
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
+134
View File
@@ -0,0 +1,134 @@
#! /bin/sh
## vim:set ts=4 sw=4 et:
set -e
#
# build UPX "by hand", using a POSIX-compliant shell and
# a minimal number of compilation flags
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
#
# uses optional environment variables: AR, CC, CXX, OPTIMIZE, VERBOSE, top_srcdir
# shell init
### set -x # enable logging
DUALCASE=1; export DUALCASE # for MKS sh
test -n "${ZSH_VERSION+set}" && emulate sh # for zsh
my_argv0="$0"
# toolchain settings and compilation flags
AR="${AR:-ar}"
CC="${CC:-cc}"
CXX="${CXX:-c++ -std=gnu++17}"
# HINT: use "export AR=false" if "$AR rcs" does not work on your system; see below
if test "x$AR" = "x0" || test "x$AR" = "xfalse" || test "x$AR" = "x/bin/false"; then
AR="" # do not use $AR
fi
# protect against security threats caused by misguided compiler "optimizations"
mandatory_flags="-fno-strict-aliasing -fno-strict-overflow -funsigned-char"
# not mandatory but good practice when using <windows.h>:
mandatory_flags="$mandatory_flags -DWIN32_LEAN_AND_MEAN"
if test "x$OPTIMIZE" != "x" && test "x$OPTIMIZE" != "x0"; then
# not mandatory and not minimal, but usually a good idea:
mandatory_flags="-Wall -O2 $mandatory_flags"
fi
CC="$CC $mandatory_flags"
CXX="$CXX $mandatory_flags"
# go to upx top-level directory
# HINT: set "top_srcdir" manually if your system does not have "readlink"
if test "x$top_srcdir" = "x"; then
my_argv0abs="$(readlink -fn "$my_argv0")"
test "x$my_argv0abs" = "x" && exit 1
my_argv0dir="$(dirname "$my_argv0abs")"
test "x$my_argv0dir" = "x" && exit 1
cd "$my_argv0dir/../.." || exit 1
else
cd "$top_srcdir" || exit 1
fi
top_srcdir="$(pwd)" # absolute
rel_top_srcdir=. # relative top_srcdir
echo "# current directory: '$(pwd)'"
test -f doc/upx.pod || exit 1 # sanity check
test -f src/version.h || exit 1 # sanity check
rm -rf ./build/by-hand # WARNING: existing build-directory gets deleted!
# helper function
run() {
if test 0 = 1; then
# DEBUG dry-run: print command, but don't actually run unless $1 is "+"
if test "x$1" = "x+"; then
shift; echo "$@"; "$@"; return
fi
shift; echo "$@"; return
fi
# print short info and run command
test "x$1" != "x" && test "x$1" != "x+" && echo "$1"
shift
if test "x$VERBOSE" != "x" && test "x$VERBOSE" != "x0"; then
# print full command
echo " $@"
fi
"$@"
}
# helper function
check_submodule() {
#local ff # "local" seems unsupported by some versions of ksh
for ff in COPYING LICENSE LICENSE.txt; do
if test -f "$rel_top_srcdir/vendor/$1/$ff"; then
# create and enter build directory; updates global $rel_top_srcdir
run "+" cd "$rel_top_srcdir" || exit 1
rel_top_srcdir=.
echo "#==== build $1 ====="
run "+" mkdir "build/by-hand/$1"
run "+" cd "build/by-hand/$1" || exit 1
rel_top_srcdir=../../..
return 0
fi
done
return 1
}
# build
run "+" mkdir -p "build/by-hand"
if check_submodule bzip2; then
for f in "$rel_top_srcdir"/vendor/bzip2/*.c; do
run "CC $f" $CC -c "$f"
done
fi
if check_submodule ucl; then
for f in "$rel_top_srcdir"/vendor/ucl/src/*.c; do
run "CC $f" $CC -I"$rel_top_srcdir"/vendor/ucl/include -I"$rel_top_srcdir"/vendor/ucl -c "$f"
done
fi
if check_submodule zlib; then
for f in "$rel_top_srcdir"/vendor/zlib/*.c; do
run "CC $f" $CC -DHAVE_UNISTD_H -DHAVE_VSNPRINTF -c "$f"
done
fi
if check_submodule zstd; then
for f in "$rel_top_srcdir"/vendor/zstd/lib/*/*.c; do
run "CC $f" $CC -DDYNAMIC_BMI2=0 -DZSTD_DISABLE_ASM -c "$f"
done
fi
run "+" cd "$rel_top_srcdir" || exit 1
rel_top_srcdir=.
echo "#==== build UPX ====="
run "+" cd "build/by-hand" || exit 1
rel_top_srcdir=../..
for f in "$rel_top_srcdir"/src/*.cpp "$rel_top_srcdir"/src/*/*.cpp; do
run "CXX $f" $CXX -I"$rel_top_srcdir"/vendor -c "$f"
done
# echo "#==== link UPX ====="
if test "x$AR" = "x"; then
# link without using $AR
run "CXX upx" $CXX -o upx *.o */*.o
else
run "AR libupx" $AR rcs libupx_submodules.a */*.o
run "CXX upx" $CXX -o upx *.o -L. -lupx_submodules
fi
echo "# current directory: '$(pwd)'"
ls -l upx*
echo "# All done."
+5 -4
View File
@@ -31,9 +31,10 @@ LC_ALL=C sort -z | xargs -0r perl -n -e '
}
}
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); }
if ($ARGV =~ m,(^|/)(gnu|m)?make(file|vars),i) { }
elsif ($ARGV =~ m,\.mk$,) { }
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
+5 -4
View File
@@ -25,9 +25,10 @@ git ls-files --full-name -z | perl -0 -n -e '
}
}
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); }
if ($ARGV =~ m,(^|/)(gnu|m)?make(file|vars),i) { }
elsif ($ARGV =~ m,\.mk$,) { }
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
+394
View File
@@ -0,0 +1,394 @@
#! /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")
# disable on macOS for now, see https://github.com/upx/upx/issues/612
if [[ "$(uname)" == Darwin ]]; then
echo "$0: SKIPPED"
exit 0
fi
# IMPORTANT NOTE: do NOT run as user root!!
# IMPORTANT NOTE: this script only works on Unix!!
umask 0022
id || true
echo "PWD='$PWD'"
if [[ $UID == 0 || $EUID == 0 ]]; then
echo "ERROR: do not run as root: UID=$UID EUID=$EUID"
exit 91
fi
# test file system behaviour with symlinks; requires:
# $upx_exe (required, but with convenience fallback "./upx")
# optional settings:
# $upx_exe_runner (e.g. "qemu-x86_64 -cpu Westmere" or "valgrind")
#***********************************************************************
# init & checks
#***********************************************************************
# upx_exe
[[ -z $upx_exe && -f ./upx && -x ./upx ]] && upx_exe=./upx # convenience fallback
if [[ -z $upx_exe ]]; then echo "UPX-ERROR: please set \$upx_exe"; exit 1; fi
if [[ ! -f $upx_exe ]]; then echo "UPX-ERROR: file '$upx_exe' does not exist"; exit 1; fi
upx_exe=$(readlink -fn "$upx_exe") # make absolute
[[ -f $upx_exe ]] || exit 1
upx_run=()
if [[ -n $upx_exe_runner ]]; then
# usage examples:
# export upx_exe_runner="qemu-x86_64 -cpu Westmere"
# export upx_exe_runner="valgrind --leak-check=no --error-exitcode=1 --quiet"
# export upx_exe_runner="wine"
IFS=' ' read -r -a upx_run <<< "$upx_exe_runner" # split at spaces into array
fi
upx_run+=( "$upx_exe" )
echo "upx_run='${upx_run[*]}'"
# upx_run check
if ! "${upx_run[@]}" --version-short >/dev/null; 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
#***********************************************************************
# util
#***********************************************************************
exit_code=0
num_errors=0
all_errors=
failed() {
####exit $1
# log error and keep going
exit_code=1
local a="$(basename "$(dirname "$PWD")")"
local b="$(basename "$PWD")"
let num_errors+=1 || true
all_errors="${all_errors} $a/$b/$1"
echo " FAILED $b/$1"
}
assert_file() {
local f
for f in "$@"; do
[[ ! -L "$f" && -f "$f" ]] && continue
echo "failed '$f': not a regular file"
failed 21
done
}
assert_symlink_to_file() {
local f
for f in "$@"; do
[[ -L "$f" && -f "$f" ]] && continue
echo "failed '$f': not a symlink to file"
failed 22
done
}
assert_symlink_to_dir() {
local f
for f in "$@"; do
[[ -L "$f" && -d "$f" ]] && continue
echo "failed '$f': not a symlink to dir"
failed 23
done
}
assert_symlink_dangling() {
local f
for f in "$@"; do
[[ -L "$f" && ! -e "$f" ]] && continue
echo "failed '$f': not a dangling symlink"
failed 24
done
}
copy_directory() {
if command -v rsync >/dev/null; then
rsync -aH "$1/" "$2"
else
cp -ai "$1" "$2"
fi
}
create_files() {
# clean
local d
for d in z_dir_1 z_dir_2 z_dir_3 z_dir_4; do
if [[ -d $d ]]; then
chmod -R +rwx "./$d"
rm -rf "./$d"
fi
done
mkdir z_dir_1
cd z_dir_1
: > z_file
ln -s z_file z_symlink_file
: > z_file_link_1
ln z_file_link_1 z_file_link_2
ln -s z_file_link_1 z_symlink_file_link
mkdir z_dir
ln -s z_dir z_symlink_dir
ln -s z_file_missing z_symlink_dangling
assert_file z_file*
assert_symlink_to_file z_symlink_file
assert_symlink_to_dir z_symlink_dir
assert_symlink_dangling z_symlink_dangling
cd ..
# write-protect z_dir_2/z_file*
copy_directory z_dir_1 z_dir_2
chmod a-w z_dir_2/z_file*
# write-protect z_dir_3 itself
copy_directory z_dir_1 z_dir_3
chmod a-w z_dir_3
# write-protect everything in z_dir_4
copy_directory z_dir_1 z_dir_4
chmod -R a-w z_dir_4
}
#***********************************************************************
#
#***********************************************************************
#set -x # debug
export UPX="--prefer-ucl --no-color --no-progress"
export UPX_DEBUG_DISABLE_GITREV_WARNING=1
export UPX_DEBUG_DOCTEST_VERBOSE=0
export NO_COLOR=1
testsuite_header() {
local x='==========='; x="$x$x$x$x$x$x$x"
echo -e "\n${x}\n${1}\n${x}\n"
}
enter_dir() {
cd "$1" || exit 1
echo "===== $(basename "$PWD")"
}
leave_dir() {
echo "===== $(basename "$PWD") files"
ls -lA
cd ..
}
# create a tmpdir in current directory
tmpdir="$(mktemp -d tmp-upx-test-XXXXXX)"
cd "./$tmpdir" || exit 1
if [[ -f /bin/ls ]]; then
test_file="$(readlink -fn /bin/ls)"
else
test_file="$(readlink -fn /usr/bin/env)"
fi
testsuite_header "default"
flags="-qq -1 --no-filter"
mkdir default
cd default
create_files
enter_dir z_dir_1
"${upx_run[@]}" $flags z_symlink_file && failed 10
"${upx_run[@]}" $flags "$test_file" -o z_file_new || failed 11
"${upx_run[@]}" $flags "$test_file" -o z_dir && failed 12
"${upx_run[@]}" $flags "$test_file" -o z_file && failed 13
"${upx_run[@]}" $flags "$test_file" -o z_file_link_1 && failed 14
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file && failed 15
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file_link && failed 16
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dir && failed 17
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dangling && failed 18
assert_symlink_to_file z_symlink_file z_symlink_file_link
assert_symlink_to_dir z_symlink_dir
assert_symlink_dangling z_symlink_dangling
leave_dir
enter_dir z_dir_2
"${upx_run[@]}" $flags z_symlink_file && failed 10
"${upx_run[@]}" $flags "$test_file" -o z_file_new || failed 11
"${upx_run[@]}" $flags "$test_file" -o z_dir && failed 12
"${upx_run[@]}" $flags "$test_file" -o z_file && failed 13
"${upx_run[@]}" $flags "$test_file" -o z_file_link_1 && failed 14
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file && failed 15
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file_link && failed 16
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dir && failed 17
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dangling && failed 18
assert_symlink_to_file z_symlink_file z_symlink_file_link
assert_symlink_to_dir z_symlink_dir
assert_symlink_dangling z_symlink_dangling
leave_dir
enter_dir z_dir_3
"${upx_run[@]}" $flags z_symlink_file && failed 10
"${upx_run[@]}" $flags "$test_file" -o z_file_new && failed 11
"${upx_run[@]}" $flags "$test_file" -o z_dir && failed 12
"${upx_run[@]}" $flags "$test_file" -o z_file && failed 13
"${upx_run[@]}" $flags "$test_file" -o z_file_link_1 && failed 14
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file && failed 15
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file_link && failed 16
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dir && failed 17
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dangling && failed 18
assert_symlink_to_file z_symlink_file z_symlink_file_link
assert_symlink_to_dir z_symlink_dir
assert_symlink_dangling z_symlink_dangling
leave_dir
enter_dir z_dir_4
"${upx_run[@]}" $flags z_symlink_file && failed 10
"${upx_run[@]}" $flags "$test_file" -o z_file_new && failed 11
"${upx_run[@]}" $flags "$test_file" -o z_dir && failed 12
"${upx_run[@]}" $flags "$test_file" -o z_file && failed 13
"${upx_run[@]}" $flags "$test_file" -o z_file_link_1 && failed 14
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file && failed 15
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file_link && failed 16
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dir && failed 17
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dangling && failed 18
assert_symlink_to_file z_symlink_file z_symlink_file_link
assert_symlink_to_dir z_symlink_dir
assert_symlink_dangling z_symlink_dangling
leave_dir
cd ..
testsuite_header "force-overwrite"
flags="-qq -1 --no-filter --force-overwrite"
mkdir force-overwrite
cd force-overwrite
create_files
enter_dir z_dir_1
"${upx_run[@]}" $flags z_symlink_file && failed 10
"${upx_run[@]}" $flags "$test_file" -o z_file_new || failed 11
"${upx_run[@]}" $flags "$test_file" -o z_dir && failed 12
"${upx_run[@]}" $flags "$test_file" -o z_file || failed 13
"${upx_run[@]}" $flags "$test_file" -o z_file_link_1 || failed 14
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file || failed 15
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file_link || failed 16
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dir || failed 17
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dangling || failed 18
assert_file z_symlink_file z_symlink_file_link
assert_file z_symlink_dir
assert_file z_symlink_dangling
leave_dir
enter_dir z_dir_2
"${upx_run[@]}" $flags z_symlink_file && failed 10
"${upx_run[@]}" $flags "$test_file" -o z_file_new || failed 11
"${upx_run[@]}" $flags "$test_file" -o z_dir && failed 12
"${upx_run[@]}" $flags "$test_file" -o z_file || failed 13
"${upx_run[@]}" $flags "$test_file" -o z_file_link_1 || failed 14
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file || failed 15
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file_link || failed 16
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dir || failed 17
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dangling || failed 18
assert_file z_symlink_file z_symlink_file_link
assert_file z_symlink_dir
assert_file z_symlink_dangling
leave_dir
enter_dir z_dir_3
"${upx_run[@]}" $flags z_symlink_file && failed 10
"${upx_run[@]}" $flags "$test_file" -o z_file_new && failed 11
"${upx_run[@]}" $flags "$test_file" -o z_dir && failed 12
"${upx_run[@]}" $flags "$test_file" -o z_file || failed 13
"${upx_run[@]}" $flags "$test_file" -o z_file_link_1 || failed 14
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file || failed 15
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file_link || failed 16
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dir && failed 17
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dangling && failed 18
assert_symlink_to_file z_symlink_file z_symlink_file_link
assert_symlink_to_dir z_symlink_dir
assert_symlink_dangling z_symlink_dangling
leave_dir
enter_dir z_dir_4
"${upx_run[@]}" $flags z_symlink_file && failed 10
"${upx_run[@]}" $flags "$test_file" -o z_file_new && failed 11
"${upx_run[@]}" $flags "$test_file" -o z_dir && failed 12
"${upx_run[@]}" $flags "$test_file" -o z_file || failed 13
"${upx_run[@]}" $flags "$test_file" -o z_file_link_1 || failed 14
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file || failed 15
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file_link || failed 16
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dir && failed 17
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dangling && failed 18
assert_symlink_to_file z_symlink_file z_symlink_file_link
assert_symlink_to_dir z_symlink_dir
assert_symlink_dangling z_symlink_dangling
leave_dir
cd ..
if [[ 1 == 1 ]]; then
testsuite_header "link"
flags="-qq -1 --no-filter --link"
mkdir link
cd link
create_files
enter_dir z_dir_1
"${upx_run[@]}" $flags z_symlink_file && failed 10
"${upx_run[@]}" $flags "$test_file" -o z_file_new || failed 11
"${upx_run[@]}" $flags "$test_file" -o z_dir && failed 12
"${upx_run[@]}" $flags "$test_file" -o z_file || failed 13
"${upx_run[@]}" $flags "$test_file" -o z_file_link_1 || failed 14
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file || failed 15
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file_link || failed 16
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dir || failed 17
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dangling || failed 18
assert_file z_symlink_file z_symlink_file_link
assert_file z_symlink_dir
assert_file z_symlink_dangling
leave_dir
enter_dir z_dir_2
"${upx_run[@]}" $flags z_symlink_file && failed 10
"${upx_run[@]}" $flags "$test_file" -o z_file_new || failed 11
"${upx_run[@]}" $flags "$test_file" -o z_dir && failed 12
"${upx_run[@]}" $flags "$test_file" -o z_file && failed 13
"${upx_run[@]}" $flags "$test_file" -o z_file_link_1 && failed 14
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file || failed 15
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file_link || failed 16
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dir || failed 17
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dangling || failed 18
assert_file z_symlink_file z_symlink_file_link
assert_file z_symlink_dir
assert_file z_symlink_dangling
leave_dir
enter_dir z_dir_3
"${upx_run[@]}" $flags z_symlink_file && failed 10
"${upx_run[@]}" $flags "$test_file" -o z_file_new && failed 11
"${upx_run[@]}" $flags "$test_file" -o z_dir && failed 12
"${upx_run[@]}" $flags "$test_file" -o z_file || failed 13
"${upx_run[@]}" $flags "$test_file" -o z_file_link_1 || failed 14
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file || failed 15
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file_link || failed 16
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dir && failed 17
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dangling && failed 18
assert_symlink_to_file z_symlink_file z_symlink_file_link
assert_symlink_to_dir z_symlink_dir
assert_symlink_dangling z_symlink_dangling
leave_dir
enter_dir z_dir_4
"${upx_run[@]}" $flags z_symlink_file && failed 10
"${upx_run[@]}" $flags "$test_file" -o z_file_new && failed 11
"${upx_run[@]}" $flags "$test_file" -o z_dir && failed 12
"${upx_run[@]}" $flags "$test_file" -o z_file && failed 13
"${upx_run[@]}" $flags "$test_file" -o z_file_link_1 && failed 14
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file || failed 15
"${upx_run[@]}" $flags "$test_file" -o z_symlink_file_link || failed 16
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dir && failed 17
"${upx_run[@]}" $flags "$test_file" -o z_symlink_dangling && failed 18
assert_symlink_to_file z_symlink_file z_symlink_file_link
assert_symlink_to_dir z_symlink_dir
assert_symlink_dangling z_symlink_dangling
leave_dir
cd ..
fi
# clean up
cd ..
chmod -R +rwx "./$tmpdir"
rm -rf "./$tmpdir"
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,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="\
fb458e6e7718ffd3f060fca911d069a024df8da7c75e34a0aea820a15ca03551 *amd64-linux.elf/upx-3.91
8988a2556bff2da1a5de9a5a4c909a53ae99a825fcdc7699d4c504bc697f60df *amd64-linux.elf/upx-3.95
b8bf6a29177bc7e9595d1c2a200f2c6431e12eee1ca2c8a64064a52c792b7b65 *amd64-win64.pe/upx-3.95.exe
02c17f49a54f50a9ed453227b600feb4ba5574514552d1cb344b1b012265afb2 *arm-linux.elf/upx-3.95
0006e29a124430722e691a05afab0a381d332c2ffe53c7f6a2cdf4cdea5349ce *arm-wince.pe/upx-3.91.exe
94a60c5859fc98db7671828decfb456e670a402a676d97cd4d66b5406c062f1f *arm64-linux.elf/upx-3.95
654a4e4cb325caddcf150ca90f2729c748bb0a3e99e703c6aad6a9dbc7d6d6e1 *armeb-linux.elf/upx-3.91
c68172e589871dc76cc7dff5464c87cd83a8cf9178d3b340e166912bcf6c9a0a *armeb-linux.elf/upx-3.95
ecc834183718c481c724754356977f4d63a58a07a2a308b9d2d669cf4d859b10 *i386-dos32.djgpp2.coff/upx-3.91.exe
879bdb9fc4c2ff76688250b429281a0a196c3723aabb40657f61a256d271b407 *i386-dos32.djgpp2.coff/upx-3.95.exe
582e7d54ba02aa4133a82ed423fce85376a3e2435468c2275e6500895f80b62d *i386-linux.elf/upx-3.91
00501788b58d4523faad8e0d0a9832d1f743e33739f8190be19094e2aa002c77 *i386-linux.elf/upx-3.95
9b9c922a6ddd48cf92af8aaa99452c101d69eb65f83e5fed6870bfe5450ca66c *i386-win32.pe/upx-3.91.exe
85a21b38b2c0ddf94bfd41b28c6a7af74accfa2246cb7f6c5881a0525cbbcdd0 *i386-win32.pe/upx-3.95.exe
993eb24cdacd30fd0ad915c88ea523f19748e4f4b3c4f7302dc233ceec67501e *m68k-atari.tos/upx-3.91.ttp
b48802d429cb7edab4d945a658a7f2aa65f67e48085ee9f40999e63cd164089b *mips-linux.elf/upx-3.95
aac26e3324c3a07d0cb41ee68dddc29891334e13ccd60bfb9138729a2f27742d *mipsel-linux.elf/upx-3.91
85803d12a0262bb424c95efff414e7882dc1104164c245ab90dff27ee5bd41db *mipsel-linux.elf/upx-3.95
e1ec8a1d392e0493c9fd60f3327d85aec108815100ab01ae65210cd26c917888 *powerpc-linux.elf/upx-3.91
845aad9ec6cba72b3a83c9958e9718938fdfd3d18ac76170d81f57c1c86987a0 *powerpc-linux.elf/upx-3.95
149efbda7f68c354d48771d838aca07cbdda503746bb83497ec8ab226dea4792 *powerpc64le-linux.elf/upx-3.95
"
expected_sha256sums__t120_compress_ucl_nrv2d_3_no_filter="\
3f1d7ad512df7cc6f1fa4fe4a37f21d92709764fc385e307504e12208c090df4 *amd64-linux.elf/upx-3.91
a9291e95bc5c59193ae318c4bf13341ade909b8a6b42694c33cb3a9d1a084637 *amd64-linux.elf/upx-3.95
968c6c681b99c6ad21f3100527da0d2f0ccc510885d6a23b1db613207aedc739 *amd64-win64.pe/upx-3.95.exe
e06b57cd0013db94ba298bef4b30d904ad8eadafb7db6b4b4964de65f9fae0ad *arm-linux.elf/upx-3.95
bf6c7ba2a464f7dfcdff230462a23f9bcfafaebddb7746f0021367076ede58ac *arm-wince.pe/upx-3.91.exe
053c60a4a376ddf3e5ac9b91933e483b86f184f02369c1df204b32acda2d72f7 *arm64-linux.elf/upx-3.95
63bbc0b63ec9504650869e0b51a6941c9d8f6d472463e9f602e26e6a21c493fc *armeb-linux.elf/upx-3.91
f0b78117ac4a4671470cbff4b10907024d3811ee4197dcaa5cad0a84c98c8693 *armeb-linux.elf/upx-3.95
86888d40e8b17fd59a1ed78264e075e1b04b57ca020c43768b37f916beb11649 *i386-dos32.djgpp2.coff/upx-3.91.exe
57f916c1f0fb33746de4c65f232258fb48acb2aa266b59ffdeac0c654bc650ca *i386-dos32.djgpp2.coff/upx-3.95.exe
efc046cd508c647651fa6574b171fb44ebf2bf785d7bd9ec3fcc6b24b01db96b *i386-linux.elf/upx-3.91
279325e2cac136e24ec928eba687849c3359ab9ce76ad9502a64d3883029ee5c *i386-linux.elf/upx-3.95
8b7aba7c9e733bb72844d797cb9f6a7225b4ce79ee62e38a9e424b4c5cc63ade *i386-win32.pe/upx-3.91.exe
e966278db2d69913989bcfddf998e8f5b35fd8045c55b1e45065fc121c2452a0 *i386-win32.pe/upx-3.95.exe
475777e4b8284a57e61cec9fa61549b06b761f6fe77ffdf24e23997eefd87036 *m68k-atari.tos/upx-3.91.ttp
fd726e5be8f899cea4ce147beb23e7697953220f680b54d9ad12ecbbf6764fd9 *mips-linux.elf/upx-3.95
36e40ec2e07cf2a095f6d1c58d5d454a486d24fa1406890ccc3dcaf3223b1ed3 *mipsel-linux.elf/upx-3.91
97a0b1e3744f4168905c6423778f9fef887a467e9f382677f1da785f2f3fd5ea *mipsel-linux.elf/upx-3.95
1576fcc71df7ac816aa3b322b9c399df017f05e99b843b98ce02be15e5ef9148 *powerpc-linux.elf/upx-3.91
768a206b9dac7816bd9b1b5c86fbfdf1f5a6920fa2cbc35e50b19d58779b219e *powerpc-linux.elf/upx-3.95
287d53686422057d5c7ddad5c30ad2a3342424153b162f3769fe8fe717b48b91 *powerpc64le-linux.elf/upx-3.95
"
expected_sha256sums__t130_compress_ucl_nrv2e_3_no_filter="\
3f04cc82752ee6c573e6ed22a44943caa1126503ad898def7452e25df14709ec *amd64-linux.elf/upx-3.91
7a3103783fb6c1e34b476e2cbeb7a5992c635dcd643d1ff37e5aeaf57f70f268 *amd64-linux.elf/upx-3.95
509be220b15f12853a26207f8c2fe361feed50203adb3af4e2bb03aab3467221 *amd64-win64.pe/upx-3.95.exe
e2e4dfb92a85a1e8d06d2d28778f63c3efec484b91c58236ce9df02cfe3e012e *arm-linux.elf/upx-3.95
18bf698a9ea039a0c3f1de9cab845dc1b51ad881e96daba4b7389adca830ecec *arm-wince.pe/upx-3.91.exe
b2155656ba70f468cc21fe0125dd2a2a9b0bf4b5d802eb399565c15b2997f1f8 *arm64-linux.elf/upx-3.95
4dab150e1309d643583ded5262dea6f5ffa82ef7e3533515d10ef3c95dc11ea5 *armeb-linux.elf/upx-3.91
25b072a5a86ead3bd9ddc539c3f29d5fd2c9cceb010657ace5eec827f73cec93 *armeb-linux.elf/upx-3.95
d7d0d5c45297d81cf4de9256c43ebbe236d1a839daeb16c900ebb5c1503659f0 *i386-dos32.djgpp2.coff/upx-3.91.exe
262fa423a8cdd765156b9385f4f1fe2fc8bba4b7e9904281f6f99a7a867ecdd1 *i386-dos32.djgpp2.coff/upx-3.95.exe
a74811a5f2b2bf26b1d64ff8e5ac5d9111bbc3022bea77b5389a2253a059c6e9 *i386-linux.elf/upx-3.91
b4c9632a18ac07b7351ea3a24e112ee32cba67eec194dc822f5211d793665d63 *i386-linux.elf/upx-3.95
b35b94f6f14e0795a3e30d04aa6cb9cb1fca6dc15a45cf99f9ce66646b438d74 *i386-win32.pe/upx-3.91.exe
11505bfed2b91ff3df360c3fcf5e701bce6c536f79f4743eff367bf4e16a686b *i386-win32.pe/upx-3.95.exe
ac45ed125aa0e5f002556e9410d32e4007cb905cf71354df20e38785a90e0ea0 *m68k-atari.tos/upx-3.91.ttp
773e144b638f23cfa2640e5c6760d6f847d477efa0c64c158e24be7efbdb765d *mips-linux.elf/upx-3.95
bd53867507b9449dc8c12007d8ed16ef332b8c4d96b1749cbd8b731a61402215 *mipsel-linux.elf/upx-3.91
a72cffc63f3415f5c913a504c2d2af30cd533f849cd7866b65a8b4c91301c475 *mipsel-linux.elf/upx-3.95
1c93b25a4846fce0d2242d753f0a6e662f018a8d63234236e88c7cf32e104d22 *powerpc-linux.elf/upx-3.91
263f4d184edab2716accbcdda2749a348a0b3d055d3096fa8c85d975c66a2342 *powerpc-linux.elf/upx-3.95
9b04dbab6863895dd3df5b0fe50086eff57e401d853a55fd9cdd06c0794e7ce7 *powerpc64le-linux.elf/upx-3.95
"
expected_sha256sums__t140_compress_lzma_2_no_filter="\
68ea7e46654a94a1c125e039b9167ee8724edf0762f5522e81cfbb94005af8fd *amd64-linux.elf/upx-3.91
7adf842624efaa46a03b1861fee62dbc01c1e22387b29fa16f530d3c6aa4d295 *amd64-linux.elf/upx-3.95
77aa80d55f83afdfb3796dfbe972b79a2195b37f84e9bb87ff7d11e497927021 *amd64-win64.pe/upx-3.95.exe
16916c440d76231df63ae5260bcf28c65476d06319d51e084f1730ab83d279bc *arm-linux.elf/upx-3.95
fae27479b40010e1d0794fe28fcc619c64a6ff21888221089fee429135658580 *arm-wince.pe/upx-3.91.exe
c7630be0a014dbef80053609329faf5bb55ca5f3abf80df26674ca311d3943ae *arm64-linux.elf/upx-3.95
4efb05939371b23037e8a0b34a35ae181d2d101afac9d3e06457d191e59a5e76 *armeb-linux.elf/upx-3.91
231d9a6e570615c2688befae04ad7ca88abe9655097e352e84cf0419190355db *armeb-linux.elf/upx-3.95
9df0142609a0a61595c500f1b9b40efab6d8c179f83068a5f4507df9a9c66d18 *i386-dos32.djgpp2.coff/upx-3.91.exe
6bdf60b30d916a9b706c7c2563907758994350b372351d7e9b1fa6427d75a01a *i386-dos32.djgpp2.coff/upx-3.95.exe
a96cc162e2a2ce59c9199534ce3c067096b655ea426b8c1ce9c4d27f282481ef *i386-linux.elf/upx-3.91
25540046329ed7bb0b071a6686d301f5cd8d3722407088514a88044a7caddc3b *i386-linux.elf/upx-3.95
93a6093dac3cb679e85900bfd60d7cf26319958245d4dc92425856c742aa95af *i386-win32.pe/upx-3.91.exe
e1cb547f4c11a58b245de0bb71e9fbedffa4d9c6f97a57ce679abbae71e0c0b9 *i386-win32.pe/upx-3.95.exe
31ba49ef577fb0031130e00198b69afec95ff9cc90806ab04d607be0627d0d1a *m68k-atari.tos/upx-3.91.ttp
69d27ee81743163b3bd9a7a9721abec70606ee38716c72410dc82bf826e508ee *mips-linux.elf/upx-3.95
6ee9682486076ea670bdfa95c7b6dd98d0274e970f7dcc7bdabda8d07558abf5 *mipsel-linux.elf/upx-3.91
b817e57dca45c26d93d2f293d77bf0a9ffa2a4232141d9e4f1a20b369c0b3bbb *mipsel-linux.elf/upx-3.95
99337dd36736e46e2ae90fcb6990746577a135d4b465e69f7f421a218e245657 *powerpc-linux.elf/upx-3.91
c1b63b66351e224cc53e33086daafefdeaf3c91a37b68426b08d2c709727f214 *powerpc-linux.elf/upx-3.95
9e28a8e6eb94549defc2a842ca24bc7a7496f581237378a118a0ee1792598ee1 *powerpc64le-linux.elf/upx-3.95
"
expected_sha256sums__t150_compress_ucl_2_all_filters="\
7b164c03af75a33c19dfa45767e9f44a754fd2fecd56239609fff37244030593 *amd64-linux.elf/upx-3.91
f591bf4b34d2bdab707506ca9e7b2822b0d9bfa1dfd542b96512fcdfe18c77d3 *amd64-linux.elf/upx-3.95
a80f6756fb9acb5ac4be3f0609c37042922c769a285eca34734eb62547ce4479 *amd64-win64.pe/upx-3.95.exe
2c249c4fd65bc53376984bfbe352d7732f49d7c601dd01773a6034c127a03416 *arm-linux.elf/upx-3.95
f640a43f3e12d092a4a8e9f34d89cc02ca85d382b80e1efdeec4ecffb09aa680 *arm-wince.pe/upx-3.91.exe
8d5df9081689113edd3cdd357535aa35e45df4339ad37479d496cbd6e873f38f *arm64-linux.elf/upx-3.95
0756666adb390b4330cf3f50eee92f73cc1d0afdbcecedd7cdf94fad29bf2c71 *armeb-linux.elf/upx-3.91
7b8156540b234aec8f6bc4db8dcd9841afd0be1385d55b07bb6f918594dcde9d *armeb-linux.elf/upx-3.95
23cc97a192c76ce849d17f5a902d178ed10918007b9667913395095db285b546 *i386-dos32.djgpp2.coff/upx-3.91.exe
66ec810d94684cfa71980a1812ec158b4485b897aac52fa4617e097d69e4d10f *i386-dos32.djgpp2.coff/upx-3.95.exe
9b004924ddc9e028e556c882366e10ed11cc8f69792f658e07b2d19d370bb102 *i386-linux.elf/upx-3.91
74453c23dba3e6f3818faf85f2dd34669839b34679da70201e071566a32df26c *i386-linux.elf/upx-3.95
e91a7748c9ebafe7987127431690ae1464d8f505267a8b3837edf5f17589534b *i386-win32.pe/upx-3.91.exe
ba4c9b76016431ff30f1ead43b77a6b4ecce9757a438d05647ae3efaa33288fa *i386-win32.pe/upx-3.95.exe
e6b493dff57c763d4feb49490353dd843b15b1a1c78c000af8bf48472e11f5ae *m68k-atari.tos/upx-3.91.ttp
cdf64a07ffa09aab14f5f467da334c41b5b496b77f65034bfca94b8f917b71f6 *mips-linux.elf/upx-3.95
cf1e80d5575766df41fcc27e08e30e3aa2b3a318a0d9014e6a7241bed8fb1d75 *mipsel-linux.elf/upx-3.91
5afd8fbe8bdb25a76dd4105dbb3e4695e4332ceec9837e0609a9850cebdc524a *mipsel-linux.elf/upx-3.95
c378615d5068a5c44cb751290c732a127f88d3534d47318be41f1827a43c41b5 *powerpc-linux.elf/upx-3.91
b4b3ebd20ee61a0ed47d481e7333cef42d1a23f832c5463aff6df640d5265e65 *powerpc-linux.elf/upx-3.95
0283de59bd2bf8f9dc11e1b5ad69d666bfc7a2b2168585ae3874f758eb271336 *powerpc64le-linux.elf/upx-3.95
"
expected_sha256sums__t160_compress_all_methods_1_no_filter="\
d2ebb0a3e77b766446b0076008c63e910b3286b72ba7c4cce03782f36c0c7396 *amd64-linux.elf/upx-3.91
3de94645a9b15b723b21da216e26577f8e28d4d296ceb5b68eacf5ea4040525c *amd64-linux.elf/upx-3.95
4106f280f30fff3c39fe72b10cf450cc514d3aa9e6769255f54606c4c09bf646 *amd64-win64.pe/upx-3.95.exe
db5838a8816241e57f3271ee217cbd99b80d2c5ec15f9c71e0b1da1cced372a3 *arm-linux.elf/upx-3.95
97a78c7aef6ab3eeb2807893c4edfb529565e36b27f9982456276dde46e34d90 *arm-wince.pe/upx-3.91.exe
50c4a83017a143e386f8e8c4f1dc73827b059ffc4a94586ab949edd19f27d4b3 *arm64-linux.elf/upx-3.95
dbf432c12845fe8cebb131995cd57cc637dee8e21e8b083ed05052a2839373d8 *armeb-linux.elf/upx-3.91
751ecfef4f02003f127d7dffe9fdf12af1a449bf4546e8a6dbc86d8885441746 *armeb-linux.elf/upx-3.95
da261516dc443ac3a9dfbe9e3353313042b72e8c1fa3f7c17bf32e0ff4221a12 *i386-dos32.djgpp2.coff/upx-3.91.exe
a4eaa51e14b7bdecff560e4ed209888cda0fde955693a7005aca67361181c561 *i386-dos32.djgpp2.coff/upx-3.95.exe
48c1959184334c5eeaddad5b2141103a0a5863a3c22f068d6d977e2fb0ed1711 *i386-linux.elf/upx-3.91
eeb2cf342f9dbb87440bd4aec0b81ea3218b300124f6348758ea4bf100318ec9 *i386-linux.elf/upx-3.95
28c742067136d6023720208131a5052553cae9cd5fa1b86ffc9d7b1338ab6466 *i386-win32.pe/upx-3.91.exe
11646ac069761715b45a78c0ad769ca69f3b2e22ff70a7068bcda7118bfc82fd *i386-win32.pe/upx-3.95.exe
0e442a98a0e90716945ffe9addf9cb7079686e3cc0f968c5e557b52a36fe6ac8 *m68k-atari.tos/upx-3.91.ttp
71abe63b1bfe35d8ff9bbaab18dcf41881a94f7bcd12bd0c010205ecbee94f33 *mips-linux.elf/upx-3.95
acc0e3322b4f22aa8e5a79962cf92b1a8ad203755dfe5bab6d2a668d274e4aab *mipsel-linux.elf/upx-3.91
e875572d1be9999b9292122d2094ae54142b268d7fda4ab12544507aaf673fe3 *mipsel-linux.elf/upx-3.95
62414bff8849020ea0e93c10595fbe10e30c5effa87d25fa8b67c77bc810ccb7 *powerpc-linux.elf/upx-3.91
5c59c4dc481c71a9b02dd39f8ac6e3aec24f6ca2864ad3ff1c7cc54ab567af9e *powerpc-linux.elf/upx-3.95
71863da15c4bd482c7ad6123895b555db86610b3cc35e7ab99897d7c9dbfcc9a *powerpc64le-linux.elf/upx-3.95
"
expected_sha256sums__t170_compress_all_methods_no_lzma_5_no_filter="\
6880572cb1b05e8b43af2cc0a56937ad4dc3fb32260092a1649164155b5e39de *amd64-linux.elf/upx-3.91
d6133ca17edfc370015f37182f5a6531830cefc688c127dbe0d45a7212838f0f *amd64-linux.elf/upx-3.95
027c3eb340c77f31bbc39bc05fb5ba56c2fc33529c445c288b6af26031172442 *amd64-win64.pe/upx-3.95.exe
7b9ef1fd569242b03ca8b4c6dabf880271cb3755cd00c08d15a77dc00bc05f83 *arm-linux.elf/upx-3.95
bbeb21e516bf50e7d35cffb364337c6f157a31ddcacc3d43a2b2dfda8b8da3be *arm-wince.pe/upx-3.91.exe
d8314cfd96fc2c9d83db69ea9746fdf5653fd3a6476f271d6c244976ab7ac9ff *arm64-linux.elf/upx-3.95
40c5647b8dbbc287e5686d1dc81e5adf8c68d35438039edac1f201b7f939977c *armeb-linux.elf/upx-3.91
047f325e6b0d3c1b0179b9574441957a64601ea67c55d53cf29dc830e34d7578 *armeb-linux.elf/upx-3.95
a1b89d28adae9b26d34d701acac3a32106fce77a380322ee0cbe4a852d692ce6 *i386-dos32.djgpp2.coff/upx-3.91.exe
fd05d0899b87dd4019c10a01d04228aca83203b801c0f5ecd8c25c225a9ab9af *i386-dos32.djgpp2.coff/upx-3.95.exe
58fa03662e605039f73ade85c00f8bc630623e6b10b304379b1c374f4a4330a1 *i386-linux.elf/upx-3.91
87d151c5e091586add28d63e08369692836db3cd1988edbf216a21370e01f0b5 *i386-linux.elf/upx-3.95
4e8bf3046e35facf27e060277c7e577ea367d05f531ccee950c34c6e3a151d66 *i386-win32.pe/upx-3.91.exe
8f1209d612991ac464f534206b6ce5999c6e689213fc468b289dd990309c312b *i386-win32.pe/upx-3.95.exe
6e7513be318b8e4ce2bb48a23bd47f0961ef745fd7f1e25d4439435334e62264 *m68k-atari.tos/upx-3.91.ttp
ea1abe9b33a31c5e27896eabf62a7a22640e91f03af336fc22a64366af196d8f *mips-linux.elf/upx-3.95
f8ee354abac9eeb83c2d3a9101b35181bebbc2d9e9253960b7ccf96b6670d711 *mipsel-linux.elf/upx-3.91
cfb11a2da4f598ad20f29a248ac8e28d45dea0a47984d47d075e24e63237ca07 *mipsel-linux.elf/upx-3.95
541188bdf23b4bf9513a6775ba186cf3d1cdf6a61a0c15177eb4111a51978397 *powerpc-linux.elf/upx-3.91
cc98a7992d9fee0af3a32c0408213198f8d2d407a44ae25d228057dfce0ef3dc *powerpc-linux.elf/upx-3.95
20409135c1b03e9f2dcf50266db27a6b7a0259cc073d2bc47b4264c64342bf8c *powerpc64le-linux.elf/upx-3.95
"
########## end .sha256sums.recreate
+329
View File
@@ -0,0 +1,329 @@
#! /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")
# very first version of the upx-testsuite; requires:
# $upx_exe (required, but with convenience fallback "./upx")
# $upx_testsuite_SRCDIR (required, but with convenience fallback)
# $upx_testsuite_BUILDDIR (optional)
#
# optional settings:
# $upx_exe_runner (e.g. "qemu-x86_64 -cpu Westmere" or "valgrind")
# $UPX_TESTSUITE_VERBOSE
# $UPX_TESTSUITE_LEVEL
#
# see https://github.com/upx/upx-testsuite.git
#***********************************************************************
# init & checks
#***********************************************************************
# upx_exe
[[ -z $upx_exe && -f ./upx && -x ./upx ]] && upx_exe=./upx # convenience fallback
if [[ -z $upx_exe ]]; then echo "UPX-ERROR: please set \$upx_exe"; exit 1; fi
if [[ ! -f $upx_exe ]]; then echo "UPX-ERROR: file '$upx_exe' does not exist"; exit 1; fi
upx_exe=$(readlink -fn "$upx_exe") # make absolute
[[ -f $upx_exe ]] || exit 1
upx_run=()
if [[ -n $upx_exe_runner ]]; then
# usage examples:
# export upx_exe_runner="qemu-x86_64 -cpu Westmere"
# export upx_exe_runner="valgrind --leak-check=no --error-exitcode=1 --quiet"
# export upx_exe_runner="wine"
IFS=' ' read -r -a upx_run <<< "$upx_exe_runner" # split at spaces into array
fi
upx_run+=( "$upx_exe" )
echo "upx_run='${upx_run[*]}'"
# upx_run check, part1
if ! "${upx_run[@]}" --version-short >/dev/null; 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
# upx_testsuite_SRCDIR
if [[ -z $upx_testsuite_SRCDIR ]]; then
# convenience fallback: search standard locations below upx top-level directory
if [[ -d "$argv0dir/../../../upx--upx-testsuite.git/files/packed" ]]; then
upx_testsuite_SRCDIR="$argv0dir/../../../upx--upx-testsuite.git"
elif [[ -d "$argv0dir/../../../upx-testsuite.git/files/packed" ]]; then
upx_testsuite_SRCDIR="$argv0dir/../../../upx-testsuite.git"
elif [[ -d "$argv0dir/../../../upx-testsuite/files/packed" ]]; then
upx_testsuite_SRCDIR="$argv0dir/../../../upx-testsuite"
fi
fi
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.git"
echo " and set (export) the envvar upx_testsuite_SRCDIR to the local file path"
exit 1
fi
upx_testsuite_SRCDIR=$(readlink -fn "$upx_testsuite_SRCDIR") # make absolute
[[ -d $upx_testsuite_SRCDIR ]] || exit 1
# upx_testsuite_BUILDDIR
if [[ -z $upx_testsuite_BUILDDIR ]]; then
upx_testsuite_BUILDDIR="./tmp-upx-testsuite"
fi
mkdir -p "$upx_testsuite_BUILDDIR" || exit 1
upx_testsuite_BUILDDIR=$(readlink -fn "$upx_testsuite_BUILDDIR") # make absolute
[[ -d $upx_testsuite_BUILDDIR ]] || exit 1
cd / && cd "$upx_testsuite_BUILDDIR" || exit 1
: > ./.mfxnobackup
# upx_run check, part2
if ! "${upx_run[@]}" --version-short >/dev/null; then
echo "UPX-ERROR: FATAL: upx --version-short FAILED"
echo "please make sure that \$upx_exe contains ABSOLUTE file paths and can be run from any directory"
echo "INFO: upx_run='${upx_run[*]}'"
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
case $UPX_TESTSUITE_LEVEL in
[0-8]) ;;
*) UPX_TESTSUITE_LEVEL=999 ;;
esac
if [[ $UPX_TESTSUITE_LEVEL == 0 ]]; then
echo "UPX testsuite SKIPPED."
exit 0
fi
#***********************************************************************
# setup
#***********************************************************************
#set -x # debug
exit_code=0
num_errors=0
all_errors=
export UPX="--prefer-ucl --no-color --no-progress"
export UPX_DEBUG_DISABLE_GITREV_WARNING=1
export UPX_DEBUG_DOCTEST_VERBOSE=0
rm -rf ./testsuite_1
mkdir testsuite_1 || exit 1
cd testsuite_1 || exit 1
#***********************************************************************
# support functions
#***********************************************************************
run_upx() {
local ec=0
if [[ $UPX_TESTSUITE_VERBOSE == 1 ]]; then
echo "LOG: '${upx_run[*]}' $*"
fi
"${upx_run[@]}" "$@" || ec=$?
if [[ $ec != 0 ]]; then
echo "FATAL: '${upx_run[*]}' $*"
echo " (exit code was $ec)"
exit 42
fi
}
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 [0-9a-zA-Z]*/* | 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 [0-9a-zA-Z]*/* | 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"
run_upx -qq --prefer-ucl "$@" "$f" -o "$testdir/$fsubdir/$fb"
run_upx -qq -d "$testdir/$fsubdir/$fb" -o "$testdir/.decompressed/$fsubdir/$fb"
done
testsuite_check_sha $testdir
run_upx -qq -l "$testdir"/*/*
run_upx -qq --file-info "$testdir"/*/*
run_upx -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/upx_testsuite_1-expected_sha256sums.sh" || 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"
run_upx -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"
run_upx -qq --prefer-ucl -1 "$f" -o "$testdir/$fsubdir/.packed/$fb"
run_upx -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
#***********************************************************************
if [[ $UPX_TESTSUITE_LEVEL -ge 2 ]]; 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_LEVEL -ge 3 ]]; 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_LEVEL -ge 4 ]]; 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_LEVEL -ge 5 ]]; 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_LEVEL -ge 6 ]]; 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_LEVEL -ge 7 ]]; 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_LEVEL -ge 8 ]]; 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: level $UPX_TESTSUITE_LEVEL"
run_upx --version-short
echo
echo "upx_exe='$upx_exe'"
ls -l "$upx_exe"
if command -v file >/dev/null; then
file "$upx_exe" || true
fi
echo "upx_run='${upx_run[*]}'"
echo "upx_testsuite_SRCDIR='$upx_testsuite_SRCDIR'"
echo "upx_testsuite_BUILDDIR='$upx_testsuite_BUILDDIR'"
echo ".sha256sums.{expected,current} counts:"
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
+39 -40
View File
@@ -1,17 +1,14 @@
#
# UPX Makefile - needs GNU make
# UPX src Makefile - needs GNU make and CMake >= 3.13
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
#
# IMPORTANT NOTE: this Makefile is deprecated - please
# directly use the CMake build instead!
MAKEFLAGS += -r
.SUFFIXES:
export SHELL = /bin/sh
# NOTE: this Makefile is deprecated - please directly use the CMake build
# instead. And see the top-level Makefile for some pre-defined CMake
# build configurations.
ifndef srcdir
srcdir := $(dir $(lastword $(MAKEFILE_LIST)))
srcdir := $(shell echo '$(srcdir)' | sed 's,/*$$,,' || echo 'ERROR')
srcdir := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))
endif
ifndef top_srcdir
top_srcdir := $(srcdir)/..
@@ -21,25 +18,30 @@ endif
# redirect to top-level CMake build
#
# NOTE that top-level Makefile .DEFAULT_GOAL is build/release
.DEFAULT_GOAL = build/debug
build/debug: $(top_srcdir)/build/debug/upx
build/release: $(top_srcdir)/build/release/upx
# shortcuts
all: build/debug build/release
debug: build/debug
.NOTPARALLEL: # because the actual builds use "cmake --parallel"
.PHONY: PHONY
.SECONDEXPANSION:
.SUFFIXES:
# shortcuts (all => debug + release)
debug: build/debug
release: build/release
all build/all: build/debug build/release
$(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"
# see https://github.com/upx/upx-testsuite.git
#
# search for the UPX testsuite -- git clone https://github.com/upx/upx-testsuite.git
@@ -56,22 +58,34 @@ endif
endif
# 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
# The expected (old) checksums are in $(top_srcdir)/misc/testsuite/upx_testsuite_1-expected_sha256sums.sh
# The actual (new) checksums are in ./tmp-upx-testsuite/testsuite_1/.sha256sums.recreate
ifneq ($(wildcard $(upx_testsuite_SRCDIR)/files/packed/.),)
ifneq ($(wildcard $(top_srcdir)/.github/travis_testsuite_1.sh),)
ifneq ($(wildcard $(top_srcdir)/misc/testsuite/upx_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-%: export upx_testsuite_BUILDDIR := ./tmp-upx-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
time -p bash $(top_srcdir)/misc/testsuite/upx_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
time -p bash $(top_srcdir)/misc/testsuite/upx_testsuite_1.sh
endif
endif
#
# "make check-whitespace"
#
ifneq ($(wildcard /usr/bin/env),) # needs bash, perl, xargs, etc.
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
#
# "make clang-format"
#
@@ -79,28 +93,13 @@ endif
# 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_EXCLUDE_FILES += conf.h miniacc.h stub/%.h
CLANG_FORMAT_EXCLUDE_FILES += p_elf.h p_elf_enum.h p_lx_% p_mach% p_unix% p_vmlin%
CLANG_FORMAT_FILES := $(sort $(wildcard *.[ch]* ../maint/src/*.[ch]* */*.[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"
#
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)
@$(top_srcdir)/misc/scripts/upx-clang-format.sh -i $(CLANG_FORMAT_FILES)
endif
# vim:set ts=8 sw=8 noet:
+331 -183
View File
@@ -26,47 +26,119 @@
*/
#pragma once
#ifndef UPX_BELE_H__
#define UPX_BELE_H__ 1
// BE - Big Endian
// LE - Little Endian
// NE - Native Endianness (aka host endianness)
// NE - Native Endianness (aka Host Endianness aka CPU Endianness)
// TE - Target Endianness (not used here, see various packers)
#if 1
// some platforms may provide their own system bswapXX() functions, so rename to avoid conflicts
#undef bswap16
#undef bswap32
#undef bswap64
#define bswap16 upx_bswap16
#define bswap32 upx_bswap32
#define bswap64 upx_bswap64
#endif
/*************************************************************************
// XE - eXtended Endian compatibility
// try to detect XX16 vs XX32 vs XX64 size mismatches
**************************************************************************/
#if 0 // permissive version using "void *"
#define REQUIRE_XE16 /*empty*/
#define REQUIRE_XE24 /*empty*/
#define REQUIRE_XE32 /*empty*/
#define REQUIRE_XE64 /*empty*/
typedef void XE16;
typedef void XE24;
typedef void XE32;
typedef void XE64;
#else // permissive version
// forward declarations
struct BE16;
struct BE32;
struct BE64;
struct LE16;
struct LE32;
struct LE64;
// Note:
// void is explicitly allowed (but there is no automatic pointer conversion because of template!)
// char is explicitly allowed
// byte is explicitly allowed
template <class T>
static inline constexpr bool is_xe16_type =
upx::is_same_any_v<T, void, char, byte, upx_int16_t, upx_uint16_t, BE16, LE16>;
template <class T>
static inline constexpr bool is_xe24_type = upx::is_same_any_v<T, void, char, byte>;
template <class T>
static inline constexpr bool is_xe32_type =
upx::is_same_any_v<T, void, char, byte, upx_int32_t, upx_uint32_t, BE32, LE32>;
template <class T>
static inline constexpr bool is_xe64_type =
upx::is_same_any_v<T, void, char, byte, upx_int64_t, upx_uint64_t, BE64, LE64>;
template <class T>
using enable_if_xe16 = std::enable_if_t<is_xe16_type<T>, T>;
template <class T>
using enable_if_xe24 = std::enable_if_t<is_xe24_type<T>, T>;
template <class T>
using enable_if_xe32 = std::enable_if_t<is_xe32_type<T>, T>;
template <class T>
using enable_if_xe64 = std::enable_if_t<is_xe64_type<T>, T>;
#define REQUIRE_XE16 template <class XE16, class = enable_if_xe16<XE16> >
#define REQUIRE_XE24 template <class XE24, class = enable_if_xe24<XE24> >
#define REQUIRE_XE32 template <class XE32, class = enable_if_xe32<XE32> >
#define REQUIRE_XE64 template <class XE64, class = enable_if_xe64<XE64> >
#endif // permissive version
/*************************************************************************
// core - NE
**************************************************************************/
static forceinline unsigned get_ne16(const void *p) {
REQUIRE_XE16
static forceinline unsigned get_ne16(const XE16 *p) noexcept {
upx_uint16_t v = 0;
upx_memcpy_inline(&v, p, sizeof(v));
return v;
}
static forceinline unsigned get_ne32(const void *p) {
REQUIRE_XE32
static forceinline unsigned get_ne32(const XE32 *p) noexcept {
upx_uint32_t v = 0;
upx_memcpy_inline(&v, p, sizeof(v));
return v;
}
static forceinline upx_uint64_t get_ne64(const void *p) {
REQUIRE_XE64
static forceinline upx_uint64_t get_ne64(const XE64 *p) noexcept {
upx_uint64_t v = 0;
upx_memcpy_inline(&v, p, sizeof(v));
return v;
}
static forceinline void set_ne16(void *p, unsigned vv) {
REQUIRE_XE16
static forceinline void set_ne16(XE16 *p, unsigned vv) noexcept {
upx_uint16_t v = (upx_uint16_t) (vv & 0xffff);
upx_memcpy_inline(p, &v, sizeof(v));
}
static forceinline void set_ne32(void *p, unsigned vv) {
REQUIRE_XE32
static forceinline void set_ne32(XE32 *p, unsigned vv) noexcept {
upx_uint32_t v = vv;
upx_memcpy_inline(p, &v, sizeof(v));
}
static forceinline void set_ne64(void *p, upx_uint64_t vv) {
REQUIRE_XE64
static forceinline void set_ne64(XE64 *p, upx_uint64_t vv) noexcept {
upx_uint64_t v = vv;
upx_memcpy_inline(p, &v, sizeof(v));
}
@@ -79,31 +151,42 @@ static forceinline void set_ne64(void *p, upx_uint64_t vv) {
ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4)
// unfortunately *not* constexpr with MSVC
static forceinline unsigned bswap16(unsigned v) { return (unsigned) _byteswap_ulong(v << 16); }
static forceinline unsigned bswap32(unsigned v) { return (unsigned) _byteswap_ulong(v); }
static forceinline upx_uint64_t bswap64(upx_uint64_t v) { return _byteswap_uint64(v); }
// unfortunately *not* constexpr with current MSVC
static forceinline unsigned bswap16(unsigned v) noexcept {
return (unsigned) _byteswap_ulong(v << 16);
}
static forceinline unsigned bswap32(unsigned v) noexcept { return (unsigned) _byteswap_ulong(v); }
static forceinline upx_uint64_t bswap64(upx_uint64_t v) noexcept { return _byteswap_uint64(v); }
#else
static forceinline constexpr unsigned bswap16(unsigned v) {
static forceinline constexpr unsigned bswap16(unsigned v) noexcept {
#if defined(__riscv) && __riscv_xlen == 64
return (unsigned) __builtin_bswap64((upx_uint64_t) v << 48);
#else
// return __builtin_bswap16((upx_uint16_t) (v & 0xffff));
// return (unsigned) __builtin_bswap64((upx_uint64_t) v << 48);
return __builtin_bswap32(v << 16);
#endif
}
static forceinline constexpr unsigned bswap32(unsigned v) {
// return (unsigned) __builtin_bswap64((upx_uint64_t) v << 32);
static forceinline constexpr unsigned bswap32(unsigned v) noexcept {
#if defined(__riscv) && __riscv_xlen == 64
return (unsigned) __builtin_bswap64((upx_uint64_t) v << 32);
#else
return __builtin_bswap32(v);
#endif
}
static forceinline constexpr upx_uint64_t bswap64(upx_uint64_t v) noexcept {
return __builtin_bswap64(v);
}
static forceinline constexpr upx_uint64_t bswap64(upx_uint64_t v) { return __builtin_bswap64(v); }
#endif
static forceinline constexpr unsigned no_bswap16(unsigned v) {
return v & 0xffff; // needed so that this is equivalent to bswap16() above
static forceinline constexpr unsigned no_bswap16(unsigned v) noexcept {
// mask is needed so that for all v: bswap16(bswap16(v)) == no_bswap16(v)
return v & 0xffff;
}
static forceinline constexpr unsigned no_bswap32(unsigned v) { return v; }
static forceinline constexpr upx_uint64_t no_bswap64(upx_uint64_t v) { return v; }
static forceinline constexpr unsigned no_bswap32(unsigned v) noexcept { return v; }
static forceinline constexpr upx_uint64_t no_bswap64(upx_uint64_t v) noexcept { return v; }
#if (ACC_ABI_BIG_ENDIAN)
#define ne16_to_be16(v) no_bswap16(v)
@@ -125,114 +208,144 @@ static forceinline constexpr upx_uint64_t no_bswap64(upx_uint64_t v) { return v;
// get/set 16/32/64
**************************************************************************/
inline unsigned get_be16(const void *p) { return ne16_to_be16(get_ne16(p)); }
inline unsigned get_be32(const void *p) { return ne32_to_be32(get_ne32(p)); }
inline upx_uint64_t get_be64(const void *p) { return ne64_to_be64(get_ne64(p)); }
inline unsigned get_le16(const void *p) { return ne16_to_le16(get_ne16(p)); }
inline unsigned get_le32(const void *p) { return ne32_to_le32(get_ne32(p)); }
inline upx_uint64_t get_le64(const void *p) { return ne64_to_le64(get_ne64(p)); }
inline void set_be16(void *p, unsigned v) { set_ne16(p, ne16_to_be16(v)); }
inline void set_be32(void *p, unsigned v) { set_ne32(p, ne32_to_be32(v)); }
inline void set_be64(void *p, upx_uint64_t v) { set_ne64(p, ne64_to_be64(v)); }
inline void set_le16(void *p, unsigned v) { set_ne16(p, ne16_to_le16(v)); }
inline void set_le32(void *p, unsigned v) { set_ne32(p, ne32_to_le32(v)); }
inline void set_le64(void *p, upx_uint64_t v) { set_ne64(p, ne64_to_le64(v)); }
REQUIRE_XE16
inline unsigned get_be16(const XE16 *p) noexcept { return ne16_to_be16(get_ne16(p)); }
REQUIRE_XE32
inline unsigned get_be32(const XE32 *p) noexcept { return ne32_to_be32(get_ne32(p)); }
REQUIRE_XE64
inline upx_uint64_t get_be64(const XE64 *p) noexcept { return ne64_to_be64(get_ne64(p)); }
REQUIRE_XE16
inline unsigned get_le16(const XE16 *p) noexcept { return ne16_to_le16(get_ne16(p)); }
REQUIRE_XE32
inline unsigned get_le32(const XE32 *p) noexcept { return ne32_to_le32(get_ne32(p)); }
REQUIRE_XE64
inline upx_uint64_t get_le64(const XE64 *p) noexcept { return ne64_to_le64(get_ne64(p)); }
REQUIRE_XE16
inline void set_be16(XE16 *p, unsigned v) noexcept { set_ne16(p, ne16_to_be16(v)); }
REQUIRE_XE32
inline void set_be32(XE32 *p, unsigned v) noexcept { set_ne32(p, ne32_to_be32(v)); }
REQUIRE_XE64
inline void set_be64(XE64 *p, upx_uint64_t v) noexcept { set_ne64(p, ne64_to_be64(v)); }
REQUIRE_XE16
inline void set_le16(XE16 *p, unsigned v) noexcept { set_ne16(p, ne16_to_le16(v)); }
REQUIRE_XE32
inline void set_le32(XE32 *p, unsigned v) noexcept { set_ne32(p, ne32_to_le32(v)); }
REQUIRE_XE64
inline void set_le64(XE64 *p, upx_uint64_t v) noexcept { set_ne64(p, ne64_to_le64(v)); }
/*************************************************************************
// get/set 24/26
**************************************************************************/
inline unsigned get_be24(const void *p) {
const unsigned char *b = ACC_CCAST(const unsigned char *, p);
REQUIRE_XE24
inline unsigned get_be24(const XE24 *p) noexcept {
const byte *b = ACC_CCAST(const byte *, p);
return (b[0] << 16) | (b[1] << 8) | (b[2] << 0);
}
inline unsigned get_le24(const void *p) {
const unsigned char *b = ACC_CCAST(const unsigned char *, p);
REQUIRE_XE24
inline unsigned get_le24(const XE24 *p) noexcept {
const byte *b = ACC_CCAST(const byte *, p);
return (b[0] << 0) | (b[1] << 8) | (b[2] << 16);
}
inline void set_be24(void *p, unsigned v) {
unsigned char *b = ACC_PCAST(unsigned char *, p);
b[0] = ACC_ICONV(unsigned char, (v >> 16) & 0xff);
b[1] = ACC_ICONV(unsigned char, (v >> 8) & 0xff);
b[2] = ACC_ICONV(unsigned char, (v >> 0) & 0xff);
REQUIRE_XE24
inline void set_be24(XE24 *p, unsigned v) noexcept {
byte *b = ACC_PCAST(byte *, p);
b[0] = ACC_ICONV(byte, (v >> 16) & 0xff);
b[1] = ACC_ICONV(byte, (v >> 8) & 0xff);
b[2] = ACC_ICONV(byte, (v >> 0) & 0xff);
}
inline void set_le24(void *p, unsigned v) {
unsigned char *b = ACC_PCAST(unsigned char *, p);
b[0] = ACC_ICONV(unsigned char, (v >> 0) & 0xff);
b[1] = ACC_ICONV(unsigned char, (v >> 8) & 0xff);
b[2] = ACC_ICONV(unsigned char, (v >> 16) & 0xff);
REQUIRE_XE24
inline void set_le24(XE24 *p, unsigned v) noexcept {
byte *b = ACC_PCAST(byte *, p);
b[0] = ACC_ICONV(byte, (v >> 0) & 0xff);
b[1] = ACC_ICONV(byte, (v >> 8) & 0xff);
b[2] = ACC_ICONV(byte, (v >> 16) & 0xff);
}
inline unsigned get_le26(const void *p) { return get_le32(p) & 0x03ffffff; }
inline unsigned get_le26(const void *p) noexcept { return get_le32(p) & 0x03ffffff; }
inline unsigned get_le19_5(const void *p) noexcept { return (get_le32(p) >> 5) & 0x0007ffff; }
inline unsigned get_le14_5(const void *p) noexcept { return (get_le32(p) >> 5) & 0x00003fff; }
inline void set_le26(void *p, unsigned v) {
inline void set_le26(void *p, unsigned v) noexcept {
// preserve the top 6 bits
#if 0
set_le32(p, (get_le32(p) & 0xfc000000) | (v & 0x03ffffff));
#else
// set_le32(p, (get_le32(p) & 0xfc000000) | (v & 0x03ffffff));
// optimized version, saving a runtime bswap32
set_ne32(p, (get_ne32(p) & ne32_to_le32(0xfc000000)) |
(ne32_to_le32(v) & ne32_to_le32(0x03ffffff)));
#endif
}
inline void set_le19_5(void *p, unsigned v) noexcept {
set_le32(p, (get_le32(p) & 0xff00001f) | ((v & 0x0007ffff) << 5));
}
inline void set_le14_5(void *p, unsigned v) noexcept {
set_le32(p, (get_le32(p) & 0xfff8001f) | ((v & 0x00003fff) << 5));
}
/*************************************************************************
// get signed values
**************************************************************************/
static forceinline int sign_extend(unsigned v, unsigned bits) {
static forceinline constexpr int sign_extend(unsigned v, unsigned bits) noexcept {
const unsigned sign_bit = 1u << (bits - 1);
v &= sign_bit | (sign_bit - 1);
v |= 0 - (v & sign_bit);
v |= 0u - (v & sign_bit);
return ACC_ICAST(int, v);
}
static forceinline upx_int64_t sign_extend(upx_uint64_t v, unsigned bits) {
static forceinline constexpr upx_int64_t sign_extend(upx_uint64_t v, unsigned bits) noexcept {
const upx_uint64_t sign_bit = 1ull << (bits - 1);
v &= sign_bit | (sign_bit - 1);
v |= 0 - (v & sign_bit);
v |= 0ull - (v & sign_bit);
return ACC_ICAST(upx_int64_t, v);
}
inline int get_be16_signed(const void *p) {
REQUIRE_XE16
inline int get_be16_signed(const XE16 *p) noexcept {
unsigned v = get_be16(p);
return sign_extend(v, 16);
}
inline int get_be24_signed(const void *p) {
REQUIRE_XE24
inline int get_be24_signed(const XE24 *p) noexcept {
unsigned v = get_be24(p);
return sign_extend(v, 24);
}
inline int get_be32_signed(const void *p) {
REQUIRE_XE32
inline int get_be32_signed(const XE32 *p) noexcept {
unsigned v = get_be32(p);
return sign_extend(v, 32);
}
inline upx_int64_t get_be64_signed(const void *p) {
REQUIRE_XE64
inline upx_int64_t get_be64_signed(const XE64 *p) noexcept {
upx_uint64_t v = get_be64(p);
return sign_extend(v, 64);
}
inline int get_le16_signed(const void *p) {
REQUIRE_XE16
inline int get_le16_signed(const XE16 *p) noexcept {
unsigned v = get_le16(p);
return sign_extend(v, 16);
}
inline int get_le24_signed(const void *p) {
REQUIRE_XE24
inline int get_le24_signed(const XE24 *p) noexcept {
unsigned v = get_le24(p);
return sign_extend(v, 24);
}
inline int get_le32_signed(const void *p) {
REQUIRE_XE32
inline int get_le32_signed(const XE32 *p) noexcept {
unsigned v = get_le32(p);
return sign_extend(v, 32);
}
inline upx_int64_t get_le64_signed(const void *p) {
REQUIRE_XE64
inline upx_int64_t get_le64_signed(const XE64 *p) noexcept {
upx_uint64_t v = get_le64(p);
return sign_extend(v, 64);
}
@@ -248,363 +361,358 @@ inline upx_int64_t get_le64_signed(const void *p) {
// to have gcc bug 17519 fixed - see http://gcc.gnu.org/PR17519 ]
**************************************************************************/
struct alignas(1) BE16 {
struct alignas(1) BE16 final {
typedef unsigned integral_conversion_type; // automatic conversion to unsigned
unsigned char d[2];
byte d[2];
BE16 &operator=(unsigned v) {
forceinline operator unsigned() const noexcept { return get_be16(d); }
forceinline BE16 &operator=(unsigned v) noexcept {
set_be16(d, v);
return *this;
}
BE16 &operator+=(unsigned v) {
BE16 &operator+=(unsigned v) noexcept {
set_be16(d, get_be16(d) + v);
return *this;
}
BE16 &operator-=(unsigned v) {
BE16 &operator-=(unsigned v) noexcept {
set_be16(d, get_be16(d) - v);
return *this;
}
BE16 &operator*=(unsigned v) {
BE16 &operator*=(unsigned v) noexcept {
set_be16(d, get_be16(d) * v);
return *this;
}
BE16 &operator/=(unsigned v) {
BE16 &operator/=(unsigned v) noexcept {
set_be16(d, get_be16(d) / v);
return *this;
}
BE16 &operator&=(unsigned v) {
BE16 &operator&=(unsigned v) noexcept {
set_be16(d, get_be16(d) & v);
return *this;
}
BE16 &operator|=(unsigned v) {
BE16 &operator|=(unsigned v) noexcept {
set_be16(d, get_be16(d) | v);
return *this;
}
BE16 &operator^=(unsigned v) {
BE16 &operator^=(unsigned v) noexcept {
set_be16(d, get_be16(d) ^ v);
return *this;
}
BE16 &operator<<=(unsigned v) {
BE16 &operator<<=(unsigned v) noexcept {
set_be16(d, get_be16(d) << v);
return *this;
}
BE16 &operator>>=(unsigned v) {
BE16 &operator>>=(unsigned v) noexcept {
set_be16(d, get_be16(d) >> v);
return *this;
}
operator unsigned() const { return get_be16(d); }
bool operator<(const BE16 &v) const { return unsigned(*this) < unsigned(v); }
bool operator==(const BE16 &x) const noexcept { return memcmp(d, x.d, sizeof(d)) == 0; }
bool operator<(const BE16 &x) const noexcept { return unsigned(*this) < unsigned(x); }
};
struct alignas(1) BE32 {
struct alignas(1) BE32 final {
typedef unsigned integral_conversion_type; // automatic conversion to unsigned
unsigned char d[4];
byte d[4];
BE32 &operator=(unsigned v) {
forceinline operator unsigned() const noexcept { return get_be32(d); }
forceinline BE32 &operator=(unsigned v) noexcept {
set_be32(d, v);
return *this;
}
BE32 &operator+=(unsigned v) {
BE32 &operator+=(unsigned v) noexcept {
set_be32(d, get_be32(d) + v);
return *this;
}
BE32 &operator-=(unsigned v) {
BE32 &operator-=(unsigned v) noexcept {
set_be32(d, get_be32(d) - v);
return *this;
}
BE32 &operator*=(unsigned v) {
BE32 &operator*=(unsigned v) noexcept {
set_be32(d, get_be32(d) * v);
return *this;
}
BE32 &operator/=(unsigned v) {
BE32 &operator/=(unsigned v) noexcept {
set_be32(d, get_be32(d) / v);
return *this;
}
BE32 &operator&=(unsigned v) {
BE32 &operator&=(unsigned v) noexcept {
set_be32(d, get_be32(d) & v);
return *this;
}
BE32 &operator|=(unsigned v) {
BE32 &operator|=(unsigned v) noexcept {
set_be32(d, get_be32(d) | v);
return *this;
}
BE32 &operator^=(unsigned v) {
BE32 &operator^=(unsigned v) noexcept {
set_be32(d, get_be32(d) ^ v);
return *this;
}
BE32 &operator<<=(unsigned v) {
BE32 &operator<<=(unsigned v) noexcept {
set_be32(d, get_be32(d) << v);
return *this;
}
BE32 &operator>>=(unsigned v) {
BE32 &operator>>=(unsigned v) noexcept {
set_be32(d, get_be32(d) >> v);
return *this;
}
operator unsigned() const { return get_be32(d); }
bool operator<(const BE32 &v) const { return unsigned(*this) < unsigned(v); }
bool operator==(const BE32 &x) const noexcept { return memcmp(d, x.d, sizeof(d)) == 0; }
bool operator<(const BE32 &x) const noexcept { return unsigned(*this) < unsigned(x); }
};
struct alignas(1) BE64 {
struct alignas(1) BE64 final {
typedef upx_uint64_t integral_conversion_type; // automatic conversion to upx_uint64_t
unsigned char d[8];
byte d[8];
BE64 &operator=(upx_uint64_t v) {
forceinline operator upx_uint64_t() const noexcept { return get_be64(d); }
forceinline BE64 &operator=(upx_uint64_t v) noexcept {
set_be64(d, v);
return *this;
}
BE64 &operator+=(upx_uint64_t v) {
BE64 &operator+=(upx_uint64_t v) noexcept {
set_be64(d, get_be64(d) + v);
return *this;
}
BE64 &operator-=(upx_uint64_t v) {
BE64 &operator-=(upx_uint64_t v) noexcept {
set_be64(d, get_be64(d) - v);
return *this;
}
BE64 &operator*=(upx_uint64_t v) {
BE64 &operator*=(upx_uint64_t v) noexcept {
set_be64(d, get_be64(d) * v);
return *this;
}
BE64 &operator/=(upx_uint64_t v) {
BE64 &operator/=(upx_uint64_t v) noexcept {
set_be64(d, get_be64(d) / v);
return *this;
}
BE64 &operator&=(upx_uint64_t v) {
BE64 &operator&=(upx_uint64_t v) noexcept {
set_be64(d, get_be64(d) & v);
return *this;
}
BE64 &operator|=(upx_uint64_t v) {
BE64 &operator|=(upx_uint64_t v) noexcept {
set_be64(d, get_be64(d) | v);
return *this;
}
BE64 &operator^=(upx_uint64_t v) {
BE64 &operator^=(upx_uint64_t v) noexcept {
set_be64(d, get_be64(d) ^ v);
return *this;
}
BE64 &operator<<=(unsigned v) {
BE64 &operator<<=(unsigned v) noexcept {
set_be64(d, get_be64(d) << v);
return *this;
}
BE64 &operator>>=(unsigned v) {
BE64 &operator>>=(unsigned v) noexcept {
set_be64(d, get_be64(d) >> v);
return *this;
}
operator upx_uint64_t() const { return get_be64(d); }
bool operator<(const BE64 &v) const { return upx_uint64_t(*this) < upx_uint64_t(v); }
bool operator==(const BE64 &x) const noexcept { return memcmp(d, x.d, sizeof(d)) == 0; }
bool operator<(const BE64 &x) const noexcept { return upx_uint64_t(*this) < upx_uint64_t(x); }
};
struct alignas(1) LE16 {
struct alignas(1) LE16 final {
typedef unsigned integral_conversion_type; // automatic conversion to unsigned
unsigned char d[2];
byte d[2];
LE16 &operator=(unsigned v) {
forceinline operator unsigned() const noexcept { return get_le16(d); }
forceinline LE16 &operator=(unsigned v) noexcept {
set_le16(d, v);
return *this;
}
LE16 &operator+=(unsigned v) {
LE16 &operator+=(unsigned v) noexcept {
set_le16(d, get_le16(d) + v);
return *this;
}
LE16 &operator-=(unsigned v) {
LE16 &operator-=(unsigned v) noexcept {
set_le16(d, get_le16(d) - v);
return *this;
}
LE16 &operator*=(unsigned v) {
LE16 &operator*=(unsigned v) noexcept {
set_le16(d, get_le16(d) * v);
return *this;
}
LE16 &operator/=(unsigned v) {
LE16 &operator/=(unsigned v) noexcept {
set_le16(d, get_le16(d) / v);
return *this;
}
LE16 &operator&=(unsigned v) {
LE16 &operator&=(unsigned v) noexcept {
set_le16(d, get_le16(d) & v);
return *this;
}
LE16 &operator|=(unsigned v) {
LE16 &operator|=(unsigned v) noexcept {
set_le16(d, get_le16(d) | v);
return *this;
}
LE16 &operator^=(unsigned v) {
LE16 &operator^=(unsigned v) noexcept {
set_le16(d, get_le16(d) ^ v);
return *this;
}
LE16 &operator<<=(unsigned v) {
LE16 &operator<<=(unsigned v) noexcept {
set_le16(d, get_le16(d) << v);
return *this;
}
LE16 &operator>>=(unsigned v) {
LE16 &operator>>=(unsigned v) noexcept {
set_le16(d, get_le16(d) >> v);
return *this;
}
operator unsigned() const { return get_le16(d); }
bool operator<(const LE16 &v) const { return unsigned(*this) < unsigned(v); }
bool operator==(const LE16 &x) const noexcept { return memcmp(d, x.d, sizeof(d)) == 0; }
bool operator<(const LE16 &x) const noexcept { return unsigned(*this) < unsigned(x); }
};
struct alignas(1) LE32 {
struct alignas(1) LE32 final {
typedef unsigned integral_conversion_type; // automatic conversion to unsigned
unsigned char d[4];
byte d[4];
LE32 &operator=(unsigned v) {
forceinline operator unsigned() const noexcept { return get_le32(d); }
forceinline LE32 &operator=(unsigned v) noexcept {
set_le32(d, v);
return *this;
}
LE32 &operator+=(unsigned v) {
LE32 &operator+=(unsigned v) noexcept {
set_le32(d, get_le32(d) + v);
return *this;
}
LE32 &operator-=(unsigned v) {
LE32 &operator-=(unsigned v) noexcept {
set_le32(d, get_le32(d) - v);
return *this;
}
LE32 &operator*=(unsigned v) {
LE32 &operator*=(unsigned v) noexcept {
set_le32(d, get_le32(d) * v);
return *this;
}
LE32 &operator/=(unsigned v) {
LE32 &operator/=(unsigned v) noexcept {
set_le32(d, get_le32(d) / v);
return *this;
}
LE32 &operator&=(unsigned v) {
LE32 &operator&=(unsigned v) noexcept {
set_le32(d, get_le32(d) & v);
return *this;
}
LE32 &operator|=(unsigned v) {
LE32 &operator|=(unsigned v) noexcept {
set_le32(d, get_le32(d) | v);
return *this;
}
LE32 &operator^=(unsigned v) {
LE32 &operator^=(unsigned v) noexcept {
set_le32(d, get_le32(d) ^ v);
return *this;
}
LE32 &operator<<=(unsigned v) {
LE32 &operator<<=(unsigned v) noexcept {
set_le32(d, get_le32(d) << v);
return *this;
}
LE32 &operator>>=(unsigned v) {
LE32 &operator>>=(unsigned v) noexcept {
set_le32(d, get_le32(d) >> v);
return *this;
}
operator unsigned() const { return get_le32(d); }
bool operator<(const LE32 &v) const { return unsigned(*this) < unsigned(v); }
bool operator==(const LE32 &x) const noexcept { return memcmp(d, x.d, sizeof(d)) == 0; }
bool operator<(const LE32 &x) const noexcept { return unsigned(*this) < unsigned(x); }
};
struct alignas(1) LE64 {
struct alignas(1) LE64 final {
typedef upx_uint64_t integral_conversion_type; // automatic conversion to upx_uint64_t
unsigned char d[8];
byte d[8];
LE64 &operator=(upx_uint64_t v) {
forceinline operator upx_uint64_t() const noexcept { return get_le64(d); }
forceinline LE64 &operator=(upx_uint64_t v) noexcept {
set_le64(d, v);
return *this;
}
LE64 &operator+=(upx_uint64_t v) {
LE64 &operator+=(upx_uint64_t v) noexcept {
set_le64(d, get_le64(d) + v);
return *this;
}
LE64 &operator-=(upx_uint64_t v) {
LE64 &operator-=(upx_uint64_t v) noexcept {
set_le64(d, get_le64(d) - v);
return *this;
}
LE64 &operator*=(upx_uint64_t v) {
LE64 &operator*=(upx_uint64_t v) noexcept {
set_le64(d, get_le64(d) * v);
return *this;
}
LE64 &operator/=(upx_uint64_t v) {
LE64 &operator/=(upx_uint64_t v) noexcept {
set_le64(d, get_le64(d) / v);
return *this;
}
LE64 &operator&=(upx_uint64_t v) {
LE64 &operator&=(upx_uint64_t v) noexcept {
set_le64(d, get_le64(d) & v);
return *this;
}
LE64 &operator|=(upx_uint64_t v) {
LE64 &operator|=(upx_uint64_t v) noexcept {
set_le64(d, get_le64(d) | v);
return *this;
}
LE64 &operator^=(upx_uint64_t v) {
LE64 &operator^=(upx_uint64_t v) noexcept {
set_le64(d, get_le64(d) ^ v);
return *this;
}
LE64 &operator<<=(unsigned v) {
LE64 &operator<<=(unsigned v) noexcept {
set_le64(d, get_le64(d) << v);
return *this;
}
LE64 &operator>>=(unsigned v) {
LE64 &operator>>=(unsigned v) noexcept {
set_le64(d, get_le64(d) >> v);
return *this;
}
operator upx_uint64_t() const { return get_le64(d); }
bool operator<(const LE64 &v) const { return upx_uint64_t(*this) < upx_uint64_t(v); }
bool operator==(const LE64 &x) const noexcept { return memcmp(d, x.d, sizeof(d)) == 0; }
bool operator<(const LE64 &x) const noexcept { return upx_uint64_t(*this) < upx_uint64_t(x); }
};
// native types
#if (ACC_ABI_BIG_ENDIAN)
typedef BE16 NE16;
typedef BE32 NE32;
typedef BE64 NE64;
#else
typedef LE16 NE16;
typedef LE32 NE32;
typedef LE64 NE64;
#endif
/*************************************************************************
// global operators (pointer addition/subtraction)
**************************************************************************/
template <class T>
inline T *operator+(T *ptr, const BE16 &v) {
inline T *operator+(T *ptr, const BE16 &v) noexcept {
return ptr + unsigned(v);
}
template <class T>
inline T *operator-(T *ptr, const BE16 &v) {
inline T *operator-(T *ptr, const BE16 &v) noexcept {
return ptr - unsigned(v);
}
template <class T>
inline T *operator+(T *ptr, const BE32 &v) {
inline T *operator+(T *ptr, const BE32 &v) noexcept {
return ptr + unsigned(v);
}
template <class T>
inline T *operator-(T *ptr, const BE32 &v) {
inline T *operator-(T *ptr, const BE32 &v) noexcept {
return ptr - unsigned(v);
}
template <class T>
inline T *operator+(T *ptr, const LE16 &v) {
inline T *operator+(T *ptr, const LE16 &v) noexcept {
return ptr + unsigned(v);
}
template <class T>
inline T *operator-(T *ptr, const LE16 &v) {
inline T *operator-(T *ptr, const LE16 &v) noexcept {
return ptr - unsigned(v);
}
template <class T>
inline T *operator+(T *ptr, const LE32 &v) {
inline T *operator+(T *ptr, const LE32 &v) noexcept {
return ptr + unsigned(v);
}
template <class T>
inline T *operator-(T *ptr, const LE32 &v) {
inline T *operator-(T *ptr, const LE32 &v) noexcept {
return ptr - unsigned(v);
}
// these are not implemented on purpose and will cause errors
template <class T>
T *operator+(T *ptr, const BE64 &v) DELETED_FUNCTION;
T *operator+(T *ptr, const BE64 &v) noexcept DELETED_FUNCTION;
template <class T>
T *operator-(T *ptr, const BE64 &v) DELETED_FUNCTION;
T *operator-(T *ptr, const BE64 &v) noexcept DELETED_FUNCTION;
template <class T>
T *operator+(T *ptr, const LE64 &v) DELETED_FUNCTION;
T *operator+(T *ptr, const LE64 &v) noexcept DELETED_FUNCTION;
template <class T>
T *operator-(T *ptr, const LE64 &v) DELETED_FUNCTION;
T *operator-(T *ptr, const LE64 &v) noexcept DELETED_FUNCTION;
/*************************************************************************
// global overloads
@@ -620,6 +728,7 @@ inline unsigned ALIGN_DOWN(const LE32 &a, unsigned b) { return ALIGN_DOWN(unsign
inline unsigned ALIGN_UP(unsigned a, const LE32 &b) { return ALIGN_UP(a, unsigned(b)); }
inline unsigned ALIGN_UP(const LE32 &a, unsigned b) { return ALIGN_UP(unsigned(a), b); }
// TODO: introduce upx::umax() and upx::umin()
inline unsigned UPX_MAX(unsigned a, const BE16 &b) { return UPX_MAX(a, unsigned(b)); }
inline unsigned UPX_MAX(const BE16 &a, unsigned b) { return UPX_MAX(unsigned(a), b); }
inline unsigned UPX_MIN(unsigned a, const BE16 &b) { return UPX_MIN(a, unsigned(b)); }
@@ -644,6 +753,47 @@ inline unsigned UPX_MIN(const LE32 &a, unsigned b) { return UPX_MIN(unsigned(a),
// misc support
**************************************************************************/
// native types
#if (ACC_ABI_BIG_ENDIAN)
typedef BE16 NE16;
typedef BE32 NE32;
typedef BE64 NE64;
#define ne16_compare be16_compare
#define ne32_compare be32_compare
#define ne64_compare be64_compare
#define ne16_compare_signed be16_compare_signed
#define ne32_compare_signed be32_compare_signed
#define ne64_compare_signed be64_compare_signed
#else
typedef LE16 NE16;
typedef LE32 NE32;
typedef LE64 NE64;
#define ne16_compare le16_compare
#define ne32_compare le32_compare
#define ne64_compare le64_compare
#define ne16_compare_signed le16_compare_signed
#define ne32_compare_signed le32_compare_signed
#define ne64_compare_signed le64_compare_signed
#endif
// <type_traits> upx_is_integral
#define TT_IS_INTEGRAL(T) \
template <> \
struct upx_is_integral<T> : public std::true_type {}; \
template <> \
struct upx_is_integral<const T> : public std::true_type {}; \
template <> \
struct upx_is_integral<volatile T> : public std::true_type {}; \
template <> \
struct upx_is_integral<const volatile T> : public std::true_type {}
TT_IS_INTEGRAL(BE16);
TT_IS_INTEGRAL(BE32);
TT_IS_INTEGRAL(BE64);
TT_IS_INTEGRAL(LE16);
TT_IS_INTEGRAL(LE32);
TT_IS_INTEGRAL(LE64);
#undef TT_IS_INTEGRAL
// for use with qsort()
extern "C" {
int __acc_cdecl_qsort be16_compare(const void *, const void *);
@@ -700,14 +850,12 @@ namespace N_BELE_RTP {
// util
namespace N_BELE_CTP {
inline const N_BELE_RTP::AbstractPolicy *getRTP(const BEPolicy * /*dummy*/) {
inline const N_BELE_RTP::AbstractPolicy *getRTP(const BEPolicy * /*dummy*/) noexcept {
return &N_BELE_RTP::be_policy;
}
inline const N_BELE_RTP::AbstractPolicy *getRTP(const LEPolicy * /*dummy*/) {
inline const N_BELE_RTP::AbstractPolicy *getRTP(const LEPolicy * /*dummy*/) noexcept {
return &N_BELE_RTP::le_policy;
}
} // namespace N_BELE_CTP
#endif /* already included */
/* vim:set ts=4 sw=4 et: */
+26 -41
View File
@@ -25,9 +25,7 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com>
*/
#ifndef UPX_BELE_H__
#error "this is an internal include file"
#endif
// this is an internal include file private to bele.h
/*************************************************************************
//
@@ -37,20 +35,20 @@
// CTP - Compile-Time Polymorphism (templates)
#define V static inline
#define S static int __acc_cdecl_qsort
#define C /*empty*/
#define C noexcept
#elif defined(BELE_RTP)
// RTP - Run-Time Polymorphism (virtual functions)
#define V virtual
#define S virtual int
#define C const
#define C const noexcept
#else
#error
#endif
#if defined(BELE_RTP)
struct AbstractPolicy {
inline AbstractPolicy() {}
virtual inline ~AbstractPolicy() {}
explicit inline AbstractPolicy() noexcept {}
virtual inline ~AbstractPolicy() noexcept {}
V bool isBE() C = 0;
V bool isLE() C = 0;
@@ -80,10 +78,11 @@ struct AbstractPolicy {
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 copy and move
AbstractPolicy(const AbstractPolicy &) DELETED_FUNCTION;
AbstractPolicy &operator=(const AbstractPolicy &) DELETED_FUNCTION;
AbstractPolicy(AbstractPolicy &&) noexcept DELETED_FUNCTION;
AbstractPolicy &operator=(AbstractPolicy &&) noexcept DELETED_FUNCTION;
// disable dynamic allocation
ACC_CXX_DISABLE_NEW_DELETE
};
@@ -91,7 +90,7 @@ private:
#if defined(BELE_RTP)
#undef C
#define C const override
#define C const noexcept override
#endif
struct BEPolicy
@@ -99,7 +98,7 @@ struct BEPolicy
final : public AbstractPolicy
#endif
{
inline BEPolicy() {}
explicit inline BEPolicy() noexcept {}
#if defined(BELE_CTP)
typedef N_BELE_RTP::BEPolicy RTP_Policy;
#elif defined(BELE_RTP)
@@ -147,10 +146,11 @@ struct BEPolicy
}
private:
// disable copy, assignment and move assignment
BEPolicy(const BEPolicy &) = delete;
BEPolicy &operator=(const BEPolicy &) = delete;
BEPolicy &operator=(BEPolicy &&) = delete;
// disable copy and move
BEPolicy(const BEPolicy &) DELETED_FUNCTION;
BEPolicy &operator=(const BEPolicy &) DELETED_FUNCTION;
BEPolicy(BEPolicy &&) noexcept DELETED_FUNCTION;
BEPolicy &operator=(BEPolicy &&) noexcept DELETED_FUNCTION;
// disable dynamic allocation
ACC_CXX_DISABLE_NEW_DELETE
};
@@ -160,7 +160,7 @@ struct LEPolicy
final : public AbstractPolicy
#endif
{
inline LEPolicy() {}
explicit inline LEPolicy() noexcept {}
#if defined(BELE_CTP)
typedef N_BELE_RTP::LEPolicy RTP_Policy;
#elif defined(BELE_RTP)
@@ -208,41 +208,26 @@ struct LEPolicy
}
private:
// disable copy, assignment and move assignment
LEPolicy(const LEPolicy &) = delete;
LEPolicy &operator=(const LEPolicy &) = delete;
LEPolicy &operator=(LEPolicy &&) = delete;
// disable copy and move
LEPolicy(const LEPolicy &) DELETED_FUNCTION;
LEPolicy &operator=(const LEPolicy &) DELETED_FUNCTION;
LEPolicy(LEPolicy &&) noexcept DELETED_FUNCTION;
LEPolicy &operator=(LEPolicy &&) noexcept DELETED_FUNCTION;
// disable dynamic allocation
ACC_CXX_DISABLE_NEW_DELETE
};
// native policy (aka host policy)
// Native Endianness policy (aka host policy)
#if (ACC_ABI_BIG_ENDIAN)
typedef BEPolicy NEPolicy;
typedef BEPolicy HostPolicy;
#elif (ACC_ABI_LITTLE_ENDIAN)
typedef LEPolicy NEPolicy;
typedef LEPolicy HostPolicy;
#else
#error "ACC_ABI_ENDIAN"
#endif
#if 0 /* UNUSED */
struct HostAlignedPolicy {
#if defined(BELE_CTP)
enum { isBE = HostPolicy::isBE, isLE = HostPolicy::isLE };
#endif
typedef upx_uint16_t U16;
typedef upx_uint32_t U32;
typedef upx_uint64_t U64;
static void compileTimeAssertions() {
COMPILE_TIME_ASSERT(sizeof(U16) == 2)
COMPILE_TIME_ASSERT(sizeof(U32) == 4)
COMPILE_TIME_ASSERT(sizeof(U64) == 8)
}
};
#endif
#undef V
#undef S
#undef C
+380 -181
View File
@@ -28,6 +28,12 @@
/*************************************************************************
// upx_doctest_check()
//
// honors environment variables:
// UPX_DEBUG_DOCTEST_DISABLE
// UPX_DEBUG_DOCTEST_VERBOSE
//
// HINT: set "UPX_DEBUG_DOCTEST_DISABLE=1" for improved debugging experience
**************************************************************************/
int upx_doctest_check(int argc, char **argv) {
@@ -37,22 +43,28 @@ int upx_doctest_check(int argc, char **argv) {
return 0;
#else
const char *e = getenv("UPX_DEBUG_DOCTEST_DISABLE");
if (!e)
e = getenv("UPX_DEBUG_DISABLE_DOCTEST"); // allow alternate spelling
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
bool minimal = true; // don't show summary
bool duration = false; // don't show timings
bool success = false; // don't show all succeeding tests
#if DEBUG
// default for debug builds: do show the [doctest] summary
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, "1") == 0) {
minimal = false;
} else if (strcmp(e, "2") == 0) {
minimal = false;
duration = true;
} else if (strcmp(e, "3") == 0) {
minimal = false;
duration = true;
success = true;
}
@@ -82,6 +94,7 @@ int upx_doctest_check() { return upx_doctest_check(0, nullptr); }
// compile-time checks
**************************************************************************/
// need extra parenthesis because the C preprocessor does not understand C++ templates
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))
@@ -92,35 +105,26 @@ ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same<unsigned long long, upx_uint64_t>::
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)
#if !(ACC_CC_MSC) // unfortunately *not* constexpr with current MSVC
ACC_COMPILE_TIME_ASSERT_HEADER(bswap16(0x04030201) == 0x0102)
ACC_COMPILE_TIME_ASSERT_HEADER(bswap32(0x04030201) == 0x01020304)
ACC_COMPILE_TIME_ASSERT_HEADER(bswap64(0x0807060504030201ull) == 0x0102030405060708ull)
ACC_COMPILE_TIME_ASSERT_HEADER(bswap16(bswap16(0xf4f3f2f1)) == no_bswap16(0xf4f3f2f1))
ACC_COMPILE_TIME_ASSERT_HEADER(bswap32(bswap32(0xf4f3f2f1)) == no_bswap32(0xf4f3f2f1))
ACC_COMPILE_TIME_ASSERT_HEADER(bswap64(bswap64(0xf8f7f6f5f4f3f2f1ull)) ==
no_bswap64(0xf8f7f6f5f4f3f2f1ull))
#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(sign_extend(0u + 0, 8) == 0)
ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 1, 8) == 1)
ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 127, 8) == 127)
ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 128, 8) == -128)
ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u - 1, 8) == -1)
ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 256, 8) == 0)
ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 257, 8) == 1)
ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 383, 8) == 127)
ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 384, 8) == -128)
ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 511, 8) == -1)
ACC_COMPILE_TIME_ASSERT_HEADER(CHAR_BIT == 8)
#if 0 // does not work with MSVC
@@ -139,92 +143,167 @@ ACC_COMPILE_TIME_ASSERT_HEADER((wchar_t) -1 > 0)
/*************************************************************************
// upx_compiler_sanity_check()
// assert a sane architecture and compiler
// (modern compilers will optimize away most of this code)
**************************************************************************/
namespace {
template <class T>
struct TestBELE {
__acc_static_noinline bool test(void) {
// POD checks
struct CheckIntegral {
struct TestT {
T a;
T x[2];
};
template <class U>
struct TestU {
U a = {};
const U b = {};
static constexpr U c = {};
U x[2] = {};
const U y[2] = {};
static constexpr U z[2] = {};
};
template <class U>
static void checkU(void) noexcept {
{
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)
U a = {};
const U b = {};
constexpr U c = {};
U x[2] = {};
const U y[2] = {};
constexpr U z[2] = {};
assert_noexcept(a == 0);
assert_noexcept(b == 0);
assert_noexcept(c == 0);
assert_noexcept(x[0] == 0 && x[1] == 0);
assert_noexcept(y[0] == 0 && y[1] == 0);
assert_noexcept(z[0] == 0 && z[1] == 0);
}
// 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;
TestU<U> t;
assert_noexcept(t.a == 0);
assert_noexcept(t.b == 0);
assert_noexcept(t.c == 0);
assert_noexcept(t.x[0] == 0 && t.x[1] == 0);
assert_noexcept(t.y[0] == 0 && t.y[1] == 0);
assert_noexcept(t.z[0] == 0 && t.z[1] == 0);
}
#if __cplusplus <= 201703L
COMPILE_TIME_ASSERT(std::is_pod<U>::value) // std::is_pod is deprecated in C++20
#endif
COMPILE_TIME_ASSERT(std::is_standard_layout<U>::value)
COMPILE_TIME_ASSERT(std::is_trivial<U>::value)
// more checks, these are probably implied by std::is_trivial
COMPILE_TIME_ASSERT(std::is_nothrow_default_constructible<U>::value)
COMPILE_TIME_ASSERT(std::is_nothrow_destructible<U>::value)
COMPILE_TIME_ASSERT(std::is_trivially_copyable<U>::value)
COMPILE_TIME_ASSERT(std::is_trivially_default_constructible<U>::value)
// UPX extras
COMPILE_TIME_ASSERT(upx_is_integral<U>::value)
COMPILE_TIME_ASSERT(upx_is_integral_v<U>)
}
static void check(void) noexcept {
{
TestT t = {};
assert_noexcept(t.a == 0);
assert_noexcept(t.x[0] == 0 && t.x[1] == 0);
}
{
const TestT t = {};
assert_noexcept(t.a == 0);
assert_noexcept(t.x[0] == 0 && t.x[1] == 0);
}
{
constexpr TestT t = {};
assert_noexcept(t.a == 0);
assert_noexcept(t.x[0] == 0 && t.x[1] == 0);
}
{
TestT t;
mem_clear(&t);
assert_noexcept(t.a == 0);
assert_noexcept(t.x[0] == 0 && t.x[1] == 0);
}
checkU<T>();
checkU<typename std::add_const<T>::type>();
}
};
template <class T>
struct CheckAlignment {
static void check(void) noexcept {
COMPILE_TIME_ASSERT_ALIGNED1(T)
struct alignas(1) Test1 {
char a;
T b;
};
struct alignas(1) Test2 {
char a;
T b[3];
};
COMPILE_TIME_ASSERT_ALIGNED1(Test1)
COMPILE_TIME_ASSERT_ALIGNED1(Test2)
Test1 t1[7];
Test2 t2[7];
COMPILE_TIME_ASSERT(sizeof(Test1) == 1 + sizeof(T))
COMPILE_TIME_ASSERT(sizeof(t1) == 7 + 7 * sizeof(T))
COMPILE_TIME_ASSERT(sizeof(Test2) == 1 + 3 * sizeof(T))
COMPILE_TIME_ASSERT(sizeof(t2) == 7 + 21 * sizeof(T))
UNUSED(t1);
UNUSED(t2);
}
};
template <class T>
struct TestBELE {
static noinline bool test(void) noexcept {
CheckIntegral<T>::check();
CheckAlignment<T>::check();
// arithmetic checks
T allbits = {};
assert_noexcept(allbits == 0);
allbits += 1;
allbits -= 2;
T v1;
v1 = 1;
v1 *= 4;
v1 /= 2;
v1 -= 1;
T v2;
v2 = 1;
assert_noexcept((v1 == v2));
assert_noexcept(!(v1 != v2));
assert_noexcept((v1 <= v2));
assert_noexcept((v1 >= v2));
assert_noexcept(!(v1 < v2));
assert_noexcept(!(v1 > v2));
v2 ^= allbits;
assert_noexcept(!(v1 == v2));
assert_noexcept((v1 != v2));
assert_noexcept((v1 <= v2));
assert_noexcept(!(v1 >= v2));
assert_noexcept((v1 < v2));
assert_noexcept(!(v1 > v2));
v2 += 2;
assert_noexcept(v1 == 1);
assert_noexcept(v2 == 0);
v1 <<= 1;
v1 |= v2;
v1 >>= 1;
v2 &= v1;
v2 /= v1;
v2 *= v1;
v1 += v2;
v1 -= v2;
assert_noexcept(v1 == 1);
assert_noexcept(v2 == 0);
if ((v1 ^ v2) != 1)
return false;
return true;
}
};
template <class A, class B>
struct TestNoAliasingStruct {
__acc_static_noinline bool test(A *a, B *b) {
static noinline bool test(A *a, B *b) noexcept {
*a = 0;
*b = 0;
*b -= 3;
@@ -232,22 +311,53 @@ struct TestNoAliasingStruct {
}
};
template <class A, class B>
__acc_static_forceinline bool testNoAliasing(A *a, B *b) {
static forceinline bool testNoAliasing(A *a, B *b) noexcept {
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; }
static inline bool inc_gt(const T x) noexcept { return x + 1 > x; }
static inline bool dec_lt(const T x) noexcept { return x - 1 < x; }
static inline bool neg_eq(const T x) noexcept { return T(0) - x == x; }
};
static noinline void throwSomeValue(int x) may_throw {
if (x < 0)
throw int(x);
else
throw size_t(x);
}
static noinline void check_basic_cxx_exception_handling(void (*func)(int)) noexcept {
bool cxx_exception_handling_works = false;
try {
func(42);
} catch (const size_t &e) {
if (e == 42)
cxx_exception_handling_works = true;
} catch (...) {
}
assert_noexcept(cxx_exception_handling_works);
}
} // namespace
#define ACC_WANT_ACC_CHK_CH 1
#undef ACCCHK_ASSERT
#include "../miniacc.h"
void upx_compiler_sanity_check(void) {
void upx_compiler_sanity_check(void) noexcept {
const char *e = getenv("UPX_DEBUG_DOCTEST_DISABLE");
if (!e)
e = getenv("UPX_DEBUG_DISABLE_DOCTEST"); // allow alternate spelling
if (e && e[0] && strcmp(e, "0") != 0) {
// If UPX_DEBUG_DOCTEST_DISABLE is set then we don't want to throw any
// exceptions in order to improve debugging experience.
} else {
// check working C++ exception handling to catch toolchain/qemu/wine/etc problems
check_basic_cxx_exception_handling(throwSomeValue);
}
#define ACC_WANT_ACC_CHK_CH 1
#undef ACCCHK_ASSERT
#define ACCCHK_ASSERT(expr) ACC_COMPILE_TIME_ASSERT(expr)
@@ -274,100 +384,117 @@ void upx_compiler_sanity_check(void) {
COMPILE_TIME_ASSERT_ALIGNED1(LE32)
COMPILE_TIME_ASSERT_ALIGNED1(LE64)
CheckIntegral<char>::check();
CheckIntegral<signed char>::check();
CheckIntegral<unsigned char>::check();
CheckIntegral<short>::check();
CheckIntegral<int>::check();
CheckIntegral<long>::check();
CheckIntegral<long long>::check();
CheckIntegral<ptrdiff_t>::check();
CheckIntegral<size_t>::check();
CheckIntegral<upx_off_t>::check();
CheckIntegral<upx_uintptr_t>::check();
COMPILE_TIME_ASSERT(sizeof(upx_charptr_unit_type) == 1)
COMPILE_TIME_ASSERT_ALIGNED1(upx_charptr_unit_type)
COMPILE_TIME_ASSERT(sizeof(*((charptr) nullptr)) == 1)
COMPILE_TIME_ASSERT(sizeof(UPX_VERSION_STRING4) == 4 + 1)
assert(strlen(UPX_VERSION_STRING4) == 4);
assert_noexcept(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);
assert_noexcept(strlen(UPX_VERSION_YEAR) == 4);
assert_noexcept(memcmp(UPX_VERSION_DATE_ISO, UPX_VERSION_YEAR, 4) == 0);
assert_noexcept(
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);
assert_noexcept(revlen == 5 || revlen == 6);
} else {
assert(revlen == 12 || revlen == 13);
assert_noexcept(revlen == 12 || revlen == 13);
}
if (revlen == 6 || revlen == 13) {
assert(gitrev[revlen - 1] == '+');
assert_noexcept(gitrev[revlen - 1] == '+');
}
}
assert(UPX_RSIZE_MAX_MEM == 805306368);
assert_noexcept(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());
#if DEBUG || 1
assert_noexcept(TestBELE<LE16>::test());
assert_noexcept(TestBELE<LE32>::test());
assert_noexcept(TestBELE<LE64>::test());
assert_noexcept(TestBELE<BE16>::test());
assert_noexcept(TestBELE<BE32>::test());
assert_noexcept(TestBELE<BE64>::test());
{
alignas(16) static const unsigned char dd[32] = {
alignas(16) static const byte 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 byte *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);
assert_noexcept(upx_adler32(d, 4) == 0x09f003f7);
assert_noexcept(upx_adler32(d, 4, 0) == 0x09ec03f6);
assert_noexcept(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);
assert_noexcept(get_be16(d) == 0xfffe);
assert_noexcept(bele->get16(d) == 0xfffe);
assert_noexcept(get_be16_signed(d) == -2);
assert_noexcept(get_be24(d) == 0xfffefd);
assert_noexcept(bele->get24(d) == 0xfffefd);
assert_noexcept(get_be24_signed(d) == -259);
assert_noexcept(get_be32(d) == 0xfffefdfc);
assert_noexcept(bele->get32(d) == 0xfffefdfc);
assert_noexcept(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);
assert_noexcept(get_le16(d) == 0xfeff);
assert_noexcept(bele->get16(d) == 0xfeff);
assert_noexcept(get_le16_signed(d) == -257);
assert_noexcept(get_le24(d) == 0xfdfeff);
assert_noexcept(bele->get24(d) == 0xfdfeff);
assert_noexcept(get_le24_signed(d) == -131329);
assert_noexcept(get_le32(d) == 0xfcfdfeff);
assert_noexcept(bele->get32(d) == 0xfcfdfeff);
assert_noexcept(get_le32_signed(d) == -50462977);
assert_noexcept(get_le64_signed(d) == -506097522914230529LL);
assert_noexcept(find_be16(d, 2, 0xfffe) == 0);
assert_noexcept(find_le16(d, 2, 0xfeff) == 0);
assert_noexcept(find_be32(d, 4, 0xfffefdfc) == 0);
assert_noexcept(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);
assert_noexcept(get_be16_signed(d) == 32638);
assert_noexcept(get_be24_signed(d) == 8355453);
assert_noexcept(get_be32_signed(d) == 2138996092);
assert_noexcept(get_be64_signed(d) == 9186918263483431288LL);
}
{
unsigned dd;
void *const d = &dd;
dd = ne32_to_le32(0xf7f6f5f4);
assert(get_le26(d) == 0x03f6f5f4);
assert_noexcept(get_le26(d) == 0x03f6f5f4);
set_le26(d, 0);
assert(get_le26(d) == 0);
assert(dd == ne32_to_le32(0xf4000000));
assert_noexcept(get_le26(d) == 0);
assert_noexcept(dd == ne32_to_le32(0xf4000000));
set_le26(d, 0xff020304);
assert(get_le26(d) == 0x03020304);
assert(dd == ne32_to_le32(0xf7020304));
assert_noexcept(get_le26(d) == 0x03020304);
assert_noexcept(dd == ne32_to_le32(0xf7020304));
}
{
upx_uint16_t a;
upx_uint32_t b;
upx_uint64_t c;
upx_uint16_t a = 0;
upx_uint32_t b = 0;
upx_uint64_t c = 0;
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);
assert_noexcept(a == 0x0201);
assert_noexcept(b == 0x04030201);
assert_noexcept(c == 0x0807060504030201ull);
assert_noexcept(get_ne16(&a) == 0x0201);
assert_noexcept(get_ne32(&b) == 0x04030201);
assert_noexcept(get_ne64(&c) == 0x0807060504030201ull);
}
#endif
#endif // DEBUG
union {
short v_short;
int v_int;
@@ -380,31 +507,56 @@ void upx_compiler_sanity_check(void) {
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));
assert_noexcept(testNoAliasing(&u.v_short, &u.b32));
assert_noexcept(testNoAliasing(&u.v_short, &u.l32));
assert_noexcept(testNoAliasing(&u.v_int, &u.b64));
assert_noexcept(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_noexcept(testNoAliasing(&u.v_short, &u.v_int));
assert_noexcept(testNoAliasing(&u.v_int, &u.v_long));
assert_noexcept(testNoAliasing(&u.v_int, &u.v_llong));
assert_noexcept(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));
assert_noexcept(TestIntegerWrap<unsigned>::inc_gt(0));
assert_noexcept(!TestIntegerWrap<unsigned>::inc_gt(UINT_MAX));
assert_noexcept(TestIntegerWrap<unsigned>::dec_lt(1));
assert_noexcept(!TestIntegerWrap<unsigned>::dec_lt(0));
assert_noexcept(TestIntegerWrap<unsigned>::neg_eq(0));
assert_noexcept(!TestIntegerWrap<unsigned>::neg_eq(1));
assert_noexcept(!TestIntegerWrap<unsigned>::neg_eq(UINT_MAX));
// 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));
assert_noexcept(TestIntegerWrap<int>::inc_gt(0));
assert_noexcept(!TestIntegerWrap<int>::inc_gt(INT_MAX));
assert_noexcept(TestIntegerWrap<int>::dec_lt(0));
assert_noexcept(!TestIntegerWrap<int>::dec_lt(INT_MIN));
assert_noexcept(TestIntegerWrap<int>::neg_eq(0));
assert_noexcept(!TestIntegerWrap<int>::neg_eq(1));
assert_noexcept(!TestIntegerWrap<int>::neg_eq(INT_MAX));
assert_noexcept(TestIntegerWrap<int>::neg_eq(INT_MIN)); // special case
}
/*************************************************************************
// some doctest test cases
**************************************************************************/
TEST_CASE("assert_noexcept") {
// just to make sure that our own assert() macros don't generate any warnings
byte dummy = 0;
byte *ptr1 = &dummy;
const byte *const ptr2 = &dummy;
void *ptr3 = nullptr;
assert(true);
assert(1);
assert(ptr1);
assert(ptr2);
assert(!ptr3);
assert_noexcept(true);
assert_noexcept(1);
assert_noexcept(ptr1);
assert_noexcept(ptr2);
assert_noexcept(!ptr3);
}
TEST_CASE("acc_vget") {
CHECK_EQ(acc_vget_int(0, 0), 0);
CHECK_EQ(acc_vget_long(1, -1), 1);
@@ -434,6 +586,7 @@ TEST_CASE("working -fno-strict-aliasing") {
*pi = -1;
ok = *pl != 0;
CHECK(ok);
UNUSED(ok);
}
TEST_CASE("working -fno-strict-overflow") {
@@ -451,10 +604,11 @@ TEST_CASE("working -fno-strict-overflow") {
i -= 1;
ok = i == INT_MAX;
CHECK(ok);
UNUSED(ok);
}
TEST_CASE("libc snprintf") {
// runtime check that Win32/MinGW <stdio.h> works as expected
// runtime check that Windows/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;
@@ -472,4 +626,49 @@ TEST_CASE("libc snprintf") {
CHECK_EQ(strcmp(buf, "-7.0.0.0.0.0.0.0.7.0xffffffffffffffff"), 0);
}
#if 0
TEST_CASE("libc qsort") {
// runtime check that libc qsort() never compares identical objects
// UPDATE: while only poor implementations of qsort() would actually do
// this, it is probably allowed by the standard; so skip this test case
struct Elem {
upx_uint16_t id;
upx_uint16_t value;
static int __acc_cdecl_qsort compare(const void *aa, const void *bb) noexcept {
const Elem *a = (const Elem *) aa;
const Elem *b = (const Elem *) bb;
assert_noexcept(a->id != b->id); // check not IDENTICAL
return a->value < b->value ? -1 : (a->value == b->value ? 0 : 1);
}
static bool check_sort(upx_sort_func_t sort, Elem *e, size_t n) {
upx_uint32_t x = 5381 + n + ((upx_uintptr_t) e & 0xff);
for (size_t i = 0; i < n; i++) {
e[i].id = (upx_uint16_t) i;
x = x * 33 + 1 + (i & 255);
e[i].value = (upx_uint16_t) x;
}
sort(e, n, sizeof(Elem), Elem::compare);
for (size_t i = 1; i < n; i++)
if very_unlikely (e[i - 1].value > e[i].value)
return false;
return true;
}
};
constexpr size_t N = 4096;
Elem e[N];
for (size_t n = 0; n <= N; n = 2 * n + 1) {
// CHECK(Elem::check_sort(qsort, e, n)); // libc qsort()
CHECK(Elem::check_sort(upx_gnomesort, e, n));
CHECK(Elem::check_sort(upx_shellsort_memswap, e, n));
CHECK(Elem::check_sort(upx_shellsort_memcpy, e, n));
#if UPX_CONFIG_USE_STABLE_SORT
upx_sort_func_t wrap_stable_sort = [](void *aa, size_t nn, size_t, upx_compare_func_t cc) {
upx_std_stable_sort<sizeof(Elem)>(aa, nn, cc);
};
CHECK(Elem::check_sort(wrap_stable_sort, e, n));
#endif
}
}
#endif
/* vim:set ts=4 sw=4 et: */
+207
View File
@@ -0,0 +1,207 @@
/* dt_cxxlib.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"
/*************************************************************************
// compile-time checks
**************************************************************************/
// need extra parenthesis because the C preprocessor does not understand C++ templates
ACC_COMPILE_TIME_ASSERT_HEADER((upx::is_same_all_v<int>) )
ACC_COMPILE_TIME_ASSERT_HEADER((upx::is_same_all_v<int, int>) )
ACC_COMPILE_TIME_ASSERT_HEADER((upx::is_same_all_v<int, int, int>) )
ACC_COMPILE_TIME_ASSERT_HEADER((!upx::is_same_all_v<int, char>) )
ACC_COMPILE_TIME_ASSERT_HEADER((!upx::is_same_all_v<int, char, int>) )
ACC_COMPILE_TIME_ASSERT_HEADER((!upx::is_same_all_v<int, int, char>) )
ACC_COMPILE_TIME_ASSERT_HEADER((!upx::is_same_any_v<int>) )
ACC_COMPILE_TIME_ASSERT_HEADER((upx::is_same_any_v<int, int>) )
ACC_COMPILE_TIME_ASSERT_HEADER((upx::is_same_any_v<int, char, int>) )
ACC_COMPILE_TIME_ASSERT_HEADER((upx::is_same_any_v<int, int, char>) )
ACC_COMPILE_TIME_ASSERT_HEADER((!upx::is_same_any_v<int, char>) )
ACC_COMPILE_TIME_ASSERT_HEADER((!upx::is_same_any_v<int, char, char>) )
ACC_COMPILE_TIME_ASSERT_HEADER((!upx::is_same_any_v<int, char, long>) )
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(int) == sizeof(int))
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof('a') == sizeof(char))
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof("") == 1)
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof("a") == 2)
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(0) == sizeof(int))
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(0L) == sizeof(long))
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(0LL) == sizeof(long long))
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(nullptr) == sizeof(void *))
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(sizeof(0)) == sizeof(size_t))
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(usizeof(0)) == sizeof(unsigned))
namespace compile_time = upx::compile_time;
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_len("ab") == 2)
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_len("abc") == 3)
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"))
/*************************************************************************
// util
**************************************************************************/
TEST_CASE("noncopyable") {
struct Test : private upx::noncopyable {
int v = 1;
};
Test t = {};
CHECK(t.v == 1);
#if (ACC_CC_MSC) // MSVC thinks that Test is not std::is_trivially_copyable; true or compiler bug?
// @COMPILER_BUG @MSVC_BUG
t.v = 0;
#else
mem_clear(&t);
#endif
CHECK(t.v == 0);
constexpr Test x = {};
static_assert(x.v == 1);
}
/*************************************************************************
// TriBool
**************************************************************************/
namespace {
template <class T>
struct TestTriBool {
static void test(bool expect_true, int x) noexcept {
static_assert(std::is_class<T>::value);
static_assert(std::is_nothrow_default_constructible<T>::value);
static_assert(std::is_nothrow_destructible<T>::value);
static_assert(std::is_standard_layout<T>::value);
static_assert(std::is_trivially_copyable<T>::value);
static_assert(sizeof(typename T::value_type) == sizeof(typename T::underlying_type));
static_assert(alignof(typename T::value_type) == alignof(typename T::underlying_type));
#if (ACC_ARCH_M68K && ACC_OS_TOS && ACC_CC_GNUC) && defined(__MINT__)
// broken compiler or broken ABI
#else
static_assert(sizeof(T) == sizeof(typename T::underlying_type));
static_assert(alignof(T) == alignof(typename T::underlying_type));
#endif
static_assert(T(false) == T::False);
static_assert(T(true) == T::True);
static_assert(T(T::False) == T::False);
static_assert(T(T::True) == T::True);
static_assert(T(T::Third) == T::Third);
static_assert(T(T::Third) == T(9));
static_assert(T(8) == T(9));
static_assert(!(T(0) == T(9)));
static_assert(!(T(1) == T(9)));
static_assert(T(T::Third) == 9);
static_assert(T(8) == 9);
static_assert(!(T(0) == 9));
static_assert(!(T(1) == 9));
constexpr T array[] = {false, true, T::Third};
static_assert(array[0].isStrictFalse());
static_assert(array[1].isStrictTrue());
static_assert(array[2].isThird());
static_assert(sizeof(array) == 3 * sizeof(T));
T a;
CHECK(!a);
CHECK(a.isStrictFalse());
CHECK(!a.isStrictTrue());
CHECK(a.isStrictBool());
CHECK(!a.isThird());
a = false;
CHECK(!a);
CHECK(a.isStrictFalse());
CHECK(!a.isStrictTrue());
CHECK(a.isStrictBool());
CHECK(!a.isThird());
a = true;
CHECK(a);
CHECK(!a.isStrictFalse());
CHECK(a.isStrictTrue());
CHECK(a.isStrictBool());
CHECK(!a.isThird());
a = T::Third;
if (expect_true)
CHECK(a);
else
CHECK(!a);
CHECK(!a.isStrictFalse());
CHECK(!a.isStrictTrue());
CHECK(!a.isStrictBool());
CHECK(a.isThird());
a = x;
if (expect_true)
CHECK(a);
else
CHECK(!a);
CHECK(!a.isStrictFalse());
CHECK(!a.isStrictTrue());
CHECK(!a.isStrictBool());
CHECK(a.isThird());
mem_clear(&a);
CHECK(a.isStrictFalse());
}
};
} // namespace
TEST_CASE("TriBool") {
using upx::TriBool, upx::tribool;
//
static_assert(!tribool(false));
static_assert(tribool(true));
static_assert(!tribool(tribool::Third));
TestTriBool<tribool>::test(false, -1);
//
TestTriBool<TriBool<upx_int8_t> >::test(false, -1);
TestTriBool<TriBool<upx_int64_t> >::test(false, -1);
//
TestTriBool<TriBool<unsigned, 2> >::test(true, 2);
TestTriBool<TriBool<upx_int8_t, 2> >::test(true, 2);
TestTriBool<TriBool<upx_uint8_t, 2> >::test(true, 2);
TestTriBool<TriBool<upx_int64_t, 2> >::test(true, 2);
TestTriBool<TriBool<upx_uint64_t, 2> >::test(true, 2);
}
/* vim:set ts=4 sw=4 et: */
+14 -6
View File
@@ -29,23 +29,31 @@
**************************************************************************/
#define DOCTEST_CONFIG_IMPLEMENT
#if !defined(UPX_DOCTEST_CONFIG_MULTITHREADING)
#define DOCTEST_CONFIG_NO_MULTITHREADING
#endif
#define DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
#if !defined(DOCTEST_CONFIG_DISABLE)
#if defined(__i386__) && defined(__MSDOS__) && defined(__DJGPP__) && defined(__GNUC__)
#define DOCTEST_CONFIG_NO_MULTITHREADING
#define DOCTEST_CONFIG_NO_POSIX_SIGNALS
#elif defined(__m68k__) && defined(__atarist__) && defined(__GNUC__)
#define DOCTEST_CONFIG_COLORS_NONE
#define DOCTEST_CONFIG_NO_MULTITHREADING
#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(UPX_DOCTEST_CONFIG_MULTITHREADING)
#define DOCTEST_CONFIG_NO_MULTITHREADING
#endif
#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
#endif // DOCTEST_CONFIG_DISABLE
/* vim:set ts=4 sw=4 et: */
+209 -22
View File
@@ -43,6 +43,7 @@ TEST_CASE("raw_bytes ptr") {
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);
UNUSED(ptr);
}
TEST_CASE("raw_bytes bounded array") {
@@ -55,6 +56,7 @@ TEST_CASE("raw_bytes bounded array") {
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);
UNUSED(buf);
}
/*************************************************************************
@@ -62,7 +64,7 @@ TEST_CASE("raw_bytes bounded array") {
**************************************************************************/
TEST_CASE("basic xspan usage") {
char buf[4] = {0, 1, 2, 3};
alignas(4) char buf[4] = {0, 1, 2, 3};
SUBCASE("XSPAN_x") {
XSPAN_0(char) a0 = nullptr;
@@ -91,6 +93,17 @@ TEST_CASE("basic xspan usage") {
CHECK_NOTHROW(raw_bytes(a0, 0));
CHECK_THROWS(raw_bytes(a0, 1));
CHECK_THROWS(raw_index_bytes(a0, 0, 0));
CHECK(raw_bytes(b0, 0) == buf);
CHECK(raw_bytes(bp, 0) == buf);
// info: these will fail if we ever add an overload for bounded-arrays
#if WITH_XSPAN >= 2
CHECK(b0.raw_size_in_bytes() == 0u);
CHECK(bp.raw_size_in_bytes() == 0u);
#endif
CHECK(raw_bytes(b0, 999999) == buf);
CHECK(raw_bytes(bp, 999999) == buf);
CHECK(raw_bytes(c0, 4) == buf);
CHECK(raw_index_bytes(c0, 1, 3) == buf + 1);
CHECK(raw_bytes(cp, 4) == buf);
@@ -101,11 +114,31 @@ TEST_CASE("basic xspan usage") {
CHECK_THROWS(raw_bytes(cs, 5));
CHECK_THROWS(raw_index_bytes(cs, 1, 4));
#endif
XSPAN_0(upx_uint16_t) c0_2 = XSPAN_TYPE_CAST(upx_uint16_t, c0 + 2);
XSPAN_P(upx_uint16_t) cp_2 = XSPAN_TYPE_CAST(upx_uint16_t, cp + 2);
XSPAN_S(upx_uint16_t) cs_2 = XSPAN_TYPE_CAST(upx_uint16_t, cs + 2);
CHECK(ptr_udiff_bytes(c0_2, c0) == 2u);
CHECK(ptr_udiff_bytes(cp_2, c0) == 2u);
CHECK(ptr_udiff_bytes(cs_2, c0) == 2u);
CHECK(ptr_udiff_bytes(c0_2, cp) == 2u);
CHECK(ptr_udiff_bytes(cp_2, cp) == 2u);
CHECK(ptr_udiff_bytes(cs_2, cp) == 2u);
CHECK(ptr_udiff_bytes(c0_2, cs) == 2u);
CHECK(ptr_udiff_bytes(cp_2, cs) == 2u);
CHECK(ptr_udiff_bytes(cs_2, cs) == 2u);
XSPAN_0(upx_uint16_t) c0_2b = XSPAN_TYPE_CAST(upx_uint16_t, c0) + 1;
XSPAN_P(upx_uint16_t) cp_2b = XSPAN_TYPE_CAST(upx_uint16_t, cp) + 1;
XSPAN_S(upx_uint16_t) cs_2b = XSPAN_TYPE_CAST(upx_uint16_t, cs) + 1;
CHECK(c0_2 == c0_2b);
CHECK(cp_2 == cp_2b);
CHECK(cs_2 == cs_2b);
CHECK(sizeof(*c0) == 1u);
CHECK(sizeof(*c0_2) == 2u);
}
SUBCASE("XSPAN_x_VAR") {
XSPAN_0_VAR(char, a0, nullptr);
XSPAN_0_VAR(char, b0, buf);
XSPAN_P_VAR(char, bp, buf);
@@ -124,7 +157,6 @@ TEST_CASE("basic xspan usage") {
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);
@@ -133,9 +165,24 @@ TEST_CASE("basic xspan usage") {
CHECK(x0 == z0p);
CHECK(xp == z0s);
#if WITH_XSPAN >= 1 || __cplusplus >= 201103L
XSPAN_0_VAR(char, a0, nullptr);
CHECK((a0 == nullptr));
CHECK_NOTHROW(raw_bytes(a0, 0));
CHECK_THROWS(raw_bytes(a0, 1));
CHECK_THROWS(raw_index_bytes(a0, 0, 0));
#endif
CHECK(raw_bytes(b0, 0) == buf);
CHECK(raw_bytes(bp, 0) == buf);
// info: these will fail if we ever add an overload for bounded-arrays
#if WITH_XSPAN >= 2
CHECK(b0.raw_size_in_bytes() == 0u);
CHECK(bp.raw_size_in_bytes() == 0u);
#endif
CHECK(raw_bytes(b0, 999999) == buf);
CHECK(raw_bytes(bp, 999999) == buf);
CHECK(raw_bytes(c0, 4) == buf);
CHECK(raw_index_bytes(c0, 1, 3) == buf + 1);
CHECK(raw_bytes(cp, 4) == buf);
@@ -146,6 +193,28 @@ TEST_CASE("basic xspan usage") {
CHECK_THROWS(raw_bytes(cs, 5));
CHECK_THROWS(raw_index_bytes(cs, 1, 4));
#endif
XSPAN_0_VAR(upx_uint16_t, c0_2, XSPAN_TYPE_CAST(upx_uint16_t, c0 + 2));
XSPAN_P_VAR(upx_uint16_t, cp_2, XSPAN_TYPE_CAST(upx_uint16_t, cp + 2));
XSPAN_S_VAR(upx_uint16_t, cs_2, XSPAN_TYPE_CAST(upx_uint16_t, cs + 2));
CHECK(ptr_udiff_bytes(c0_2, c0) == 2u);
CHECK(ptr_udiff_bytes(cp_2, c0) == 2u);
CHECK(ptr_udiff_bytes(cs_2, c0) == 2u);
CHECK(ptr_udiff_bytes(c0_2, cp) == 2u);
CHECK(ptr_udiff_bytes(cp_2, cp) == 2u);
CHECK(ptr_udiff_bytes(cs_2, cp) == 2u);
CHECK(ptr_udiff_bytes(c0_2, cs) == 2u);
CHECK(ptr_udiff_bytes(cp_2, cs) == 2u);
CHECK(ptr_udiff_bytes(cs_2, cs) == 2u);
XSPAN_0_VAR(upx_uint16_t, c0_2b, XSPAN_TYPE_CAST(upx_uint16_t, c0) + 1);
XSPAN_P_VAR(upx_uint16_t, cp_2b, XSPAN_TYPE_CAST(upx_uint16_t, cp) + 1);
XSPAN_S_VAR(upx_uint16_t, cs_2b, XSPAN_TYPE_CAST(upx_uint16_t, cs) + 1);
CHECK(c0_2 == c0_2b);
CHECK(cp_2 == cp_2b);
CHECK(cs_2 == cs_2b);
CHECK(sizeof(*c0) == 1u);
CHECK(sizeof(*c0_2) == 2u);
}
SUBCASE("xspan in class") {
@@ -382,6 +451,7 @@ TEST_CASE("PtrOrSpan") {
CHECK_THROWS(sp_with_base = s0_no_base); // nullptr assignment
CHECK_THROWS(sp_with_base = s0_with_base); // nullptr assignment
#endif
UNUSED(my_null);
}
/*************************************************************************
@@ -533,6 +603,7 @@ TEST_CASE("Span") {
CHECK((XSPAN_S_MAKE(char, b1_b1).raw_base() == base_buf + 1));
}
#endif
UNUSED(my_null);
}
/*************************************************************************
@@ -592,6 +663,8 @@ TEST_CASE("Span subspan") {
TEST_CASE("Span constness") {
static char buf[4] = {0, 1, 2, 3};
// NOLINTBEGIN(performance-unnecessary-copy-initialization)
XSPAN_0(char) b0(buf, 4);
XSPAN_P(char) bp(buf, 4);
XSPAN_S(char) bs(buf, 4);
@@ -612,6 +685,8 @@ TEST_CASE("Span constness") {
XSPAN_P(const char) xpc(bp);
XSPAN_S(const char) xsc(bs);
// NOLINTEND(performance-unnecessary-copy-initialization)
CHECK(ptr_diff_bytes(b0, buf) == 0);
CHECK(ptr_diff_bytes(bp, buf) == 0);
CHECK(ptr_diff_bytes(bs, buf) == 0);
@@ -659,6 +734,7 @@ TEST_CASE("PtrOrSpan") {
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);
UNUSED(buf);
}
/*************************************************************************
@@ -720,30 +796,52 @@ TEST_CASE("PtrOrSpan char") {
}
TEST_CASE("PtrOrSpan int") {
int buf[8] = {0, 1, 2, 3, 4, 5, 6, 7};
XSPAN_P(int) a(buf, XSpanCount(8));
int buf[8] = {0, 11, 22, 33, 44, 55, 66, 77};
XSPAN_P(const int) a(buf, XSpanCount(8));
CHECK(a.raw_size_in_bytes() == 8 * sizeof(int));
XSPAN_P(int) b = a.subspan(0, 7);
XSPAN_P(const int) b = a.subspan(0, 7);
CHECK(b.raw_size_in_bytes() == 7 * sizeof(int));
XSPAN_P(int) c = (b + 1).subspan(0, 6);
XSPAN_P(const 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(a == buf + 1);
CHECK(*a == 11);
CHECK(*a++ == 11);
CHECK(a == buf + 2);
CHECK(*a == 22);
CHECK(*++a == 33);
CHECK(a == buf + 3);
CHECK(*a == 33);
CHECK(*--a == 22);
CHECK(a == buf + 2);
CHECK(*a == 22);
CHECK(*a-- == 22);
CHECK(a == buf + 1);
CHECK(*a == 11);
CHECK(*b == 0);
CHECK(*c == 1);
a = buf + 7;
CHECK(*c == 11);
a -= 1;
a += 7;
#ifdef UPX_VERSION_HEX
CHECK(get_le32(a) == ne32_to_le32(7));
CHECK(get_le32(a) == ne32_to_le32(77));
#endif
a++;
#ifdef UPX_VERSION_HEX
CHECK_THROWS(get_le32(a));
#endif
CHECK_THROWS(raw_bytes(a, 1));
CHECK_THROWS(a++);
CHECK_THROWS(++a);
CHECK_THROWS(a += 1);
CHECK(a == buf + 8);
a = buf;
CHECK_THROWS(a--);
CHECK_THROWS(--a);
CHECK_THROWS(a -= 1);
CHECK_THROWS(a += 9);
CHECK(a == buf);
a += 8;
CHECK(a == buf + 8);
}
/*************************************************************************
@@ -752,12 +850,15 @@ TEST_CASE("PtrOrSpan int") {
namespace {
template <class T>
__acc_static_noinline int foo(T p) {
static noinline int foo(T p) {
unsigned r = 0;
r += *p++;
r += *++p;
p += 3;
r += *p;
r += *--p;
r += *p--;
r += *p;
return r;
}
@@ -779,13 +880,99 @@ make_span_s(T *ptr, size_t 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);
upx_uint8_t buf[8] = {0, 1, 2, 3, 4, 5, 6, 7};
CHECK(foo(buf) == 0 + 2 + 5 + 4 + 4 + 3);
CHECK(foo(make_span_0(buf, 8)) == 0 + 2 + 5 + 4 + 4 + 3);
CHECK(foo(make_span_p(buf, 8)) == 0 + 2 + 5 + 4 + 4 + 3);
CHECK(foo(make_span_s(buf, 8)) == 0 + 2 + 5 + 4 + 4 + 3);
CHECK(foo(XSPAN_0_MAKE(upx_uint8_t, buf, 8)) == 0 + 2 + 5 + 4 + 4 + 3);
CHECK(foo(XSPAN_P_MAKE(upx_uint8_t, buf, 8)) == 0 + 2 + 5 + 4 + 4 + 3);
CHECK(foo(XSPAN_S_MAKE(upx_uint8_t, buf, 8)) == 0 + 2 + 5 + 4 + 4 + 3);
UNUSED(buf);
}
#endif // WITH_XSPAN >= 2
/*************************************************************************
// misc
**************************************************************************/
namespace {
template <class T>
struct PointerTraits {
typedef typename std::add_lvalue_reference<T>::type reference;
typedef
typename std::add_lvalue_reference<typename std::add_const<T>::type>::type const_reference;
typedef typename std::add_pointer<T>::type pointer;
typedef typename std::add_pointer<typename std::add_const<T>::type>::type const_pointer;
};
} // namespace
#if __cplusplus >= 201103L
TEST_CASE("decltype integral constants") {
static_assert((std::is_same<decltype(0), int>::value), "");
static_assert((std::is_same<decltype(0u), unsigned>::value), "");
static_assert((std::is_same<decltype(0l), long>::value), "");
static_assert((std::is_same<decltype(0ul), unsigned long>::value), "");
static_assert((std::is_same<decltype(0ll), long long>::value), "");
static_assert((std::is_same<decltype(0ull), unsigned long long>::value), "");
static_assert((std::is_same<decltype((char) 0), char>::value), "");
static_assert((std::is_same<decltype((short) 0), short>::value), "");
static_assert((std::is_same<decltype((long) 0), long>::value), "");
static_assert((std::is_same<decltype((long long) 0), long long>::value), "");
static_assert((std::is_same<decltype(char(0)), char>::value), "");
static_assert((std::is_same<decltype(short(0)), short>::value), "");
static_assert((std::is_same<decltype(long(0)), long>::value), "");
}
TEST_CASE("decltype pointer") {
int dummy = 0;
int *p = &dummy;
const int *c = &dummy;
static_assert((std::is_same<decltype(p - p), std::ptrdiff_t>::value), "");
static_assert((std::is_same<decltype(c - c), std::ptrdiff_t>::value), "");
static_assert((std::is_same<decltype(p - c), std::ptrdiff_t>::value), "");
static_assert((std::is_same<decltype(c - p), std::ptrdiff_t>::value), "");
typedef PointerTraits<int> TInt;
typedef PointerTraits<const int> TConstInt;
static_assert((std::is_same<int *, TInt::pointer>::value), "");
static_assert((std::is_same<const int *, TInt::const_pointer>::value), "");
static_assert((std::is_same<const int *, TConstInt::pointer>::value), "");
static_assert((std::is_same<const int *, TConstInt::const_pointer>::value), "");
//
static_assert((std::is_same<decltype(p), TInt::pointer>::value), "");
static_assert((std::is_same<decltype(c), TInt::const_pointer>::value), "");
static_assert((std::is_same<decltype(c), TConstInt::pointer>::value), "");
static_assert((std::is_same<decltype(p + 1), TInt::pointer>::value), "");
static_assert((std::is_same<decltype(c + 1), TInt::const_pointer>::value), "");
static_assert((std::is_same<decltype(c + 1), TConstInt::pointer>::value), "");
static_assert((std::is_same<decltype(c + 1), TConstInt::const_pointer>::value), "");
static_assert((std::is_same<decltype(c + 1), const int *>::value), "");
// dereference
static_assert((std::is_same<decltype(*p), TInt::reference>::value), "");
static_assert((std::is_same<decltype(*c), TInt::const_reference>::value), "");
#if 0
// this works, but avoid clang warnings:
// "Expression with side effects has no effect in an unevaluated context"
static_assert((std::is_same<decltype(*p++), TInt::reference>::value), "");
static_assert((std::is_same<decltype(*++p), TInt::reference>::value), "");
static_assert((std::is_same<decltype(*c++), TInt::const_reference>::value), "");
static_assert((std::is_same<decltype(*c++), TConstInt::reference>::value), "");
static_assert((std::is_same<decltype(*c++), TConstInt::const_reference>::value), "");
static_assert((std::is_same<decltype(*++c), TInt::const_reference>::value), "");
static_assert((std::is_same<decltype(*++c), TConstInt::reference>::value), "");
static_assert((std::is_same<decltype(*++c), TConstInt::const_reference>::value), "");
#endif
// array access
static_assert((std::is_same<decltype(p[0]), TInt::reference>::value), "");
static_assert((std::is_same<decltype(c[0]), TInt::const_reference>::value), "");
static_assert((std::is_same<decltype(c[0]), TConstInt::reference>::value), "");
static_assert((std::is_same<decltype(c[0]), TConstInt::const_reference>::value), "");
UNUSED(p);
UNUSED(c);
}
#endif // __cplusplus >= 201103L
/* vim:set ts=4 sw=4 et: */
+8 -2
View File
@@ -78,12 +78,12 @@ int upx_compress(const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned
// force users to provide *dst_len
assert(*dst_len != 0);
#endif
// for UPX, we always require a reasonably sized outbut buffer
// for UPX, we always require a reasonably sized output buffer
assert(*dst_len >= MemBuffer::getSizeForCompression(src_len));
if (!cresult)
cresult = &cresult_buffer;
memset(cresult, 0, sizeof(*cresult));
cresult->reset();
#if 1
// debugging aid
cresult->debug.method = method;
@@ -92,6 +92,7 @@ int upx_compress(const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned
cresult->debug.c_len = 0;
#endif
const unsigned orig_dst_len = *dst_len;
if (__acc_cte(false)) {
}
#if (WITH_LZMA)
@@ -118,6 +119,7 @@ int upx_compress(const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned
// debugging aid
cresult->debug.c_len = *dst_len;
#endif
assert_noexcept(*dst_len <= orig_dst_len);
return r;
}
@@ -135,6 +137,7 @@ int upx_decompress(const upx_bytep src, unsigned src_len, upx_bytep dst, unsigne
if (cresult && cresult->debug.method == 0)
cresult = nullptr;
const unsigned orig_dst_len = *dst_len;
if (__acc_cte(false)) {
}
#if (WITH_LZMA)
@@ -161,6 +164,7 @@ int upx_decompress(const upx_bytep src, unsigned src_len, upx_bytep dst, unsigne
throwInternalError("unknown decompression method");
}
assert_noexcept(*dst_len <= orig_dst_len);
return r;
}
@@ -180,6 +184,7 @@ int upx_test_overlap(const upx_bytep buf, const upx_bytep tbuf, unsigned src_off
unsigned overlap_overhead = src_off + src_len - *dst_len;
assert((int) overlap_overhead > 0);
const unsigned orig_dst_len = *dst_len;
if (__acc_cte(false)) {
}
#if (WITH_LZMA)
@@ -202,6 +207,7 @@ int upx_test_overlap(const upx_bytep buf, const upx_bytep tbuf, unsigned src_off
throwInternalError("unknown decompression method");
}
assert_noexcept(*dst_len <= orig_dst_len);
return r;
}
+2 -10
View File
@@ -25,8 +25,8 @@
*/
#pragma once
#ifndef UPX_COMPRESS_H__
#define UPX_COMPRESS_H__ 1
// clang-format off
/*************************************************************************
//
@@ -53,7 +53,6 @@ int upx_bzip2_test_overlap ( const upx_bytep buf,
const upx_compress_result_t *cresult );
#endif
#if (WITH_LZMA)
int upx_lzma_init(void);
const char *upx_lzma_version_string(void);
@@ -75,7 +74,6 @@ int upx_lzma_test_overlap ( const upx_bytep buf,
const upx_compress_result_t *cresult );
#endif
#if (WITH_NRV)
int upx_nrv_init(void);
const char *upx_nrv_version_string(void);
@@ -97,7 +95,6 @@ int upx_nrv_test_overlap ( const upx_bytep buf,
const upx_compress_result_t *cresult );
#endif
#if (WITH_UCL)
int upx_ucl_init(void);
const char *upx_ucl_version_string(void);
@@ -121,7 +118,6 @@ unsigned upx_ucl_adler32(const void *buf, unsigned len, unsigned adler);
unsigned upx_ucl_crc32 (const void *buf, unsigned len, unsigned crc);
#endif
#if (WITH_ZLIB)
int upx_zlib_init(void);
const char *upx_zlib_version_string(void);
@@ -145,7 +141,6 @@ 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);
@@ -167,7 +162,4 @@ int upx_zstd_test_overlap ( const upx_bytep buf,
const upx_compress_result_t *cresult );
#endif
#endif /* already included */
/* vim:set ts=4 sw=4 et: */
+27 -18
View File
@@ -41,7 +41,7 @@
#pragma warning(disable : 4127) // warning C4127: conditional expression is constant
#endif
void lzma_compress_config_t::reset() {
void lzma_compress_config_t::reset() noexcept {
pos_bits.reset();
lit_pos_bits.reset();
lit_context_bits.reset();
@@ -116,7 +116,7 @@ static bool prepare_result(lzma_compress_result_t *res, unsigned src_len, int me
res->lit_context_bits = (method >> 8) & 15;
}
#if 0
// DEBUG - set sizes so that we use a maxmimum amount of stack.
// DEBUG - set sizes so that we use a maximum 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;
@@ -194,8 +194,8 @@ static bool prepare_result(lzma_compress_result_t *res, unsigned src_len, int me
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);
NO_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:
@@ -206,14 +206,23 @@ error:
// compress - cruft because of pseudo-COM layer
**************************************************************************/
// ensure proper nullptr usage
// TODO later: examine why we need this in the first place
#undef NULL
// NOLINTBEGIN(clang-analyzer-optin.cplusplus.*)
#define NULL nullptr
// NOLINTEND(clang-analyzer-optin.cplusplus.*)
#if defined(__GNUC__)
#undef __null
#define __null nullptr
#endif
#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>
@@ -375,7 +384,7 @@ int upx_lzma_compress(const upx_bytep src, unsigned src_len, upx_bytep dst, unsi
// 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)));
os.WriteByte(Byte((res->lit_pos_bits << 4) | res->lit_context_bits));
// compress
rh = enc.Code(&is, &os, nullptr, nullptr, &progress);
@@ -399,10 +408,10 @@ int upx_lzma_compress(const upx_bytep src, unsigned src_len, upx_bytep dst, unsi
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);
NO_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);
NO_printf("%u %u %u\n", is.__m_RefCount, os.__m_RefCount, progress.__m_RefCount);
return r;
}
@@ -426,7 +435,7 @@ int upx_lzma_decompress(const upx_bytep src, unsigned src_len, upx_bytep dst, un
COMPILE_TIME_ASSERT(LZMA_LIT_SIZE == 768)
CLzmaDecoderState s;
memset(&s, 0, sizeof(s));
mem_clear(&s);
SizeT src_out = 0, dst_out = 0;
int r = UPX_E_ERROR;
int rh;
@@ -458,8 +467,8 @@ int upx_lzma_decompress(const upx_bytep src, unsigned src_len, upx_bytep dst, un
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);
NO_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));
@@ -524,13 +533,12 @@ const char *upx_lzma_version_string(void) { return "4.43"; }
**************************************************************************/
TEST_CASE("upx_lzma_decompress") {
typedef const upx_byte C;
C *c_data;
upx_byte d_buf[16];
const byte *c_data;
byte d_buf[16];
unsigned d_len;
int r;
c_data = (C *) "\x1a\x03\x00\x7f\xed\x3c\x00\x00\x00";
c_data = (const byte *) "\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));
@@ -539,6 +547,7 @@ TEST_CASE("upx_lzma_decompress") {
d_len = 15;
r = upx_lzma_decompress(c_data, 9, d_buf, &d_len, M_LZMA, nullptr);
CHECK(r == UPX_E_OUTPUT_OVERRUN);
UNUSED(r);
}
/* vim:set ts=4 sw=4 et: */
+12 -10
View File
@@ -56,6 +56,8 @@ static int convert_errno_from_ucl(int r) {
// UCL extra:
case UCL_E_OVERLAP_OVERRUN:
return UPX_E_ERROR;
default:
break;
}
return UPX_E_ERROR;
}
@@ -113,14 +115,14 @@ int upx_ucl_compress(const upx_bytep src, unsigned src_len, upx_bytep dst, unsig
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};
static const upx_uint8_t 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
// optimize compression params
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)
@@ -241,9 +243,9 @@ int upx_ucl_test_overlap(const upx_bytep buf, const upx_bytep tbuf, unsigned src
**************************************************************************/
extern "C" {
static ucl_voidp __UCL_CDECL my_malloc(ucl_uint n) { return calloc(1, n); }
static ucl_voidp __UCL_CDECL my_malloc(ucl_uint n) { return upx_calloc(n, 1); }
static void __UCL_CDECL my_free(ucl_voidp p) { free(p); }
}
} // extern "C"
int upx_ucl_init(void) {
if (ucl_init() != UCL_E_OK)
@@ -327,13 +329,12 @@ TEST_CASE("compress_ucl") {
#endif // DEBUG
TEST_CASE("upx_ucl_decompress") {
typedef const upx_byte C;
C *c_data;
upx_byte d_buf[16];
const byte *c_data;
byte d_buf[16];
unsigned d_len;
int r;
c_data = (C *) "\x92\xff\x10\x00\x00\x00\x00\x00\x48\xff";
c_data = (const byte *) "\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));
@@ -343,7 +344,7 @@ TEST_CASE("upx_ucl_decompress") {
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";
c_data = (const byte *) "\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));
@@ -353,7 +354,7 @@ TEST_CASE("upx_ucl_decompress") {
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";
c_data = (const byte *) "\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));
@@ -362,6 +363,7 @@ TEST_CASE("upx_ucl_decompress") {
d_len = 15;
r = upx_ucl_decompress(c_data, 9, d_buf, &d_len, M_NRV2E_8, nullptr);
CHECK(r == UPX_E_OUTPUT_OVERRUN);
UNUSED(r);
}
/* vim:set ts=4 sw=4 et: */
+13 -9
View File
@@ -27,12 +27,14 @@
#include "../conf.h"
#include "compress.h"
#include "../util/membuffer.h"
// NOLINTBEGIN(clang-analyzer-optin.performance.Padding)
#define ZLIB_CONST 1
#include <zlib/zlib.h>
#include <zlib/deflate.h>
// NOLINTEND(clang-analyzer-optin.performance.Padding)
void zlib_compress_config_t::reset() {
mem_clear(this, sizeof(*this));
void zlib_compress_config_t::reset() noexcept {
mem_clear(this);
mem_level.reset();
window_bits.reset();
strategy.reset();
@@ -62,6 +64,8 @@ static int convert_errno_from_zlib(int zr) {
return UPX_E_ERROR;
case -7: // UPX extra
return UPX_E_INPUT_OVERRUN;
default:
break;
}
return UPX_E_ERROR;
}
@@ -100,7 +104,7 @@ int upx_zlib_compress(const upx_bytep src, unsigned src_len, upx_bytep dst, unsi
z_stream s;
s.zalloc = (alloc_func) nullptr;
s.zfree = (free_func) nullptr;
s.next_in = ACC_UNCONST_CAST(upx_bytep, src);
s.next_in = src;
s.avail_in = src_len;
s.next_out = dst;
s.avail_out = *dst_len;
@@ -149,7 +153,7 @@ int upx_zlib_decompress(const upx_bytep src, unsigned src_len, upx_bytep dst, un
z_stream s;
s.zalloc = (alloc_func) nullptr;
s.zfree = (free_func) nullptr;
s.next_in = ACC_UNCONST_CAST(upx_bytep, src);
s.next_in = src;
s.avail_in = src_len;
s.next_out = dst;
s.avail_out = *dst_len;
@@ -287,13 +291,12 @@ TEST_CASE("compress_zlib") {
#endif // DEBUG
TEST_CASE("upx_zlib_decompress") {
typedef const upx_byte C;
C *c_data;
upx_byte d_buf[16];
const byte *c_data;
byte d_buf[16];
unsigned d_len;
int r;
c_data = (C *) "\xfb\xff\x1f\x15\x00\x00";
c_data = (const byte *) "\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));
@@ -302,6 +305,7 @@ TEST_CASE("upx_zlib_decompress") {
d_len = 15;
r = upx_zlib_decompress(c_data, 6, d_buf, &d_len, M_DEFLATE, nullptr);
CHECK(r == UPX_E_OUTPUT_OVERRUN);
UNUSED(r);
}
/* vim:set ts=4 sw=4 et: */
+4 -5
View File
@@ -26,7 +26,7 @@
#include "../conf.h"
void zstd_compress_config_t::reset() { mem_clear(this, sizeof(*this)); }
void zstd_compress_config_t::reset() noexcept { mem_clear(this); }
#if WITH_ZSTD
#include "compress.h"
@@ -207,13 +207,12 @@ TEST_CASE("compress_zstd") {
#endif // DEBUG
TEST_CASE("upx_zstd_decompress") {
typedef const upx_byte C;
C *c_data;
upx_byte d_buf[32];
const byte *c_data;
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";
c_data = (const byte *) "\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));
+213 -312
View File
@@ -26,43 +26,27 @@
*/
#pragma once
#ifndef UPX_CONF_H__
#define UPX_CONF_H__ 1
#if !(__cplusplus+0 >= 201703L)
# error "C++ 17 is required"
#endif
#include "version.h"
#if !defined(_FILE_OFFSET_BITS)
# define _FILE_OFFSET_BITS 64
#endif
#if defined(_WIN32) && defined(__MINGW32__) && defined(__GNUC__)
# if !defined(_USE_MINGW_ANSI_STDIO)
# define _USE_MINGW_ANSI_STDIO 1
# endif
#endif
/*************************************************************************
// ACC and system includes
// init
**************************************************************************/
#ifndef ACC_CFG_USE_NEW_STYLE_CASTS
#define ACC_CFG_USE_NEW_STYLE_CASTS 1
#include "headers.h"
#include "version.h"
#if !defined(__has_attribute)
#define __has_attribute(x) 0
#endif
#define ACC_CFG_PREFER_TYPEOF_ACC_INT32E_T ACC_TYPEOF_INT
#define ACC_CFG_PREFER_TYPEOF_ACC_INT64E_T ACC_TYPEOF_LONG_LONG
#include "miniacc.h"
#if !(ACC_CC_CLANG || ACC_CC_GNUC || ACC_CC_MSC)
// other compilers may work, but we're NOT interested into supporting them
# error "only clang, gcc and msvc are officially supported"
#if !defined(__has_builtin)
#define __has_builtin(x) 0
#endif
// UPX sanity checks for a sane compiler
#if !defined(UINT_MAX) || (UINT_MAX != 0xffffffffL)
# error "UINT_MAX"
#if !defined(__has_feature)
#define __has_feature(x) 0
#endif
// reserve name "upx" for namespace
namespace upx {}
ACC_COMPILE_TIME_ASSERT_HEADER(CHAR_BIT == 8)
ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(short) == 2)
ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 4)
@@ -76,94 +60,79 @@ ACC_COMPILE_TIME_ASSERT_HEADER((-1) >> 31 == -1) // arithmetic right shift
ACC_COMPILE_TIME_ASSERT_HEADER(CHAR_MAX == 255) // -funsigned-char
ACC_COMPILE_TIME_ASSERT_HEADER((char)(-1) == 255) // -funsigned-char
// enable/disable some warnings
// enable some more strict warnings for Git developer builds
#if defined(UPX_CONFIG_DISABLE_WSTRICT) && (UPX_CONFIG_DISABLE_WSTRICT + 0 == 0)
#if defined(UPX_CONFIG_DISABLE_WERROR) && (UPX_CONFIG_DISABLE_WERROR + 0 == 0)
#if (ACC_CC_CLANG >= 0x0b0000)
# pragma clang diagnostic error "-Wsuggest-override"
#elif (ACC_CC_GNUC >= 0x0a0000)
// don't enable before gcc-10 because of gcc bug #78010
# pragma GCC diagnostic error "-Wsuggest-override"
#endif
#if (ACC_CC_CLANG >= 0x080000)
// don't enable before clang-8 because of stddef.h issues
# pragma clang diagnostic error "-Wzero-as-null-pointer-constant"
#elif (ACC_CC_GNUC >= 0x040700) && defined(__GLIBC__)
// Some non-GLIBC toolchains do not use 'nullptr' everywhere when C++:
// openwrt-sdk-x86-64_gcc-11.2.0_musl.Linux-x86_64/staging_dir/
// toolchain-x86_64_gcc-11.2.0_musl/include/fortify/stdlib.h:
// 51:32: error: zero as null pointer constant
#if (ACC_CC_CLANG >= 0x050000)
# pragma clang diagnostic error "-Wzero-as-null-pointer-constant"
#elif (ACC_CC_GNUC >= 0x040700) && defined(__GLIBC__)
# pragma GCC diagnostic error "-Wzero-as-null-pointer-constant"
#endif
#endif // UPX_CONFIG_DISABLE_WERROR
#endif // UPX_CONFIG_DISABLE_WSTRICT
#if (ACC_CC_MSC)
# pragma warning(error: 4127)
# pragma warning(error: 4146)
# pragma warning(error: 4319)
# pragma warning(error: 4805)
# pragma warning(disable: 4244) // -Wconversion
# pragma warning(disable: 4267) // -Wconversion
# pragma warning(disable: 4820) // padding added after data member
#endif
#undef snprintf
#undef vsnprintf
#define HAVE_STDINT_H 1
#define ACC_WANT_ACC_INCD_H 1
#define ACC_WANT_ACC_INCE_H 1
#define ACC_WANT_ACC_LIB_H 1
#define ACC_WANT_ACC_CXX_H 1
#include "miniacc.h"
#if (ACC_CC_MSC)
# include <intrin.h>
#endif
// C++ system headers
#include <exception>
#include <new>
#include <type_traits>
#include <typeinfo>
#if __STDC_NO_ATOMICS__ || 1
// UPX currently does not use multithreading
#define upx_std_atomic(Type) Type
//#define upx_std_atomic(Type) typename std::add_volatile<Type>::type
#else
#include <atomic>
// multithreading (UPX currently does not use multithreading)
#if (WITH_THREADS)
#define upx_thread_local thread_local
#define upx_std_atomic(Type) std::atomic<Type>
#endif
#define upx_std_once_flag std::once_flag
#define upx_std_call_once std::call_once
#else
#define upx_thread_local /*empty*/
#define upx_std_atomic(Type) Type
#define upx_std_once_flag upx_std_atomic(size_t)
template <class NoexceptCallable>
inline void upx_std_call_once(upx_std_once_flag &flag, NoexceptCallable &&f) {
if (__acc_unlikely(!flag)) { flag = 1; f(); }
}
#endif // WITH_THREADS
// C++ submodule headers
#include <doctest/doctest/parts/doctest_fwd.h>
#if WITH_BOOST_PFR
# include <sstream>
# include <boost/pfr/io.hpp>
#endif
#if WITH_RANGELESS_FN
# include <rangeless/include/fn.hpp>
#endif
#ifndef WITH_VALGRIND
# define WITH_VALGRIND 1
#endif
#if defined(__SANITIZE_ADDRESS__) || defined(_WIN32) || !defined(__GNUC__)
# undef WITH_VALGRIND
#endif
#if (WITH_VALGRIND)
# include <valgrind/include/valgrind/memcheck.h>
#endif
// IMPORTANT: unconditionally enable assertions
#undef NDEBUG
#include <assert.h>
// <type_traits> C++20 std::is_bounded_array
// <type_traits> upx_is_integral is overloaded for BE16 & friends; see bele.h
template <class T>
struct std_is_bounded_array : public std::false_type {};
template <class T, size_t N>
struct std_is_bounded_array<T[N]> : public std::true_type {};
struct upx_is_integral : public std::is_integral<T> {};
template <class T>
inline constexpr bool upx_is_integral_v = upx_is_integral<T>::value;
#if (ACC_ARCH_M68K && ACC_OS_TOS && ACC_CC_GNUC) && defined(__MINT__)
// horrible hack for broken compiler / ABI
#define upx_fake_alignas_1 __attribute__((__aligned__(1),__packed__))
#define upx_fake_alignas_2 __attribute__((__aligned__(2)))
#define upx_fake_alignas_4 __attribute__((__aligned__(2))) // object file maximum 2 ???
#define upx_fake_alignas_16 __attribute__((__aligned__(2))) // object file maximum 2 ???
#define upx_fake_alignas__(x) upx_fake_alignas_ ## x
#define alignas(x) upx_fake_alignas__(x)
#define upx_alignas_max upx_fake_alignas_4
#endif
#ifndef upx_alignas_max
#define upx_alignas_max alignas(std::max_align_t)
#endif
/*************************************************************************
// core
**************************************************************************/
// intergral types
// protect against integer overflows and malicious header fields
// see C 11 standard, Annex K
//
// this limits uncompressed_size to about 682 MiB (715_128_832 bytes)
typedef size_t upx_rsize_t;
#define UPX_RSIZE_MAX UPX_RSIZE_MAX_MEM
#define UPX_RSIZE_MAX_MEM (768 * 1024 * 1024) // DO NOT CHANGE !!!
#define UPX_RSIZE_MAX_STR (256 * 1024)
// integral types
typedef acc_int8_t upx_int8_t;
typedef acc_uint8_t upx_uint8_t;
typedef acc_int16_t upx_int16_t;
@@ -174,21 +143,23 @@ typedef acc_int64_t upx_int64_t;
typedef acc_uint64_t upx_uint64_t;
typedef acc_uintptr_t upx_uintptr_t;
typedef unsigned char upx_byte;
#define upx_bytep upx_byte *
// protect against integer overflows and malicious header fields
// see C 11 standard, Annex K
typedef size_t upx_rsize_t;
#define UPX_RSIZE_MAX UPX_RSIZE_MAX_MEM
#define UPX_RSIZE_MAX_MEM (768 * 1024 * 1024) // DO NOT CHANGE !!!
#define UPX_RSIZE_MAX_STR (1024 * 1024)
// convention: use "byte" when dealing with data; use "char/uchar" when dealing
// with strings; use "upx_uint8_t" when dealing with small integers
typedef unsigned char byte;
#define upx_byte byte
#define upx_bytep byte *
typedef unsigned char uchar;
// convention: use "charptr" when dealing with abstract pointer arithmetics
#define charptr upx_charptr_unit_type *
// upx_charptr_unit_type is some opaque type with sizeof(type) == 1
struct alignas(1) upx_charptr_unit_type { char hidden__; };
ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(upx_charptr_unit_type) == 1)
// using the system off_t was a bad idea even back in 199x...
typedef upx_int64_t upx_off_t;
#undef off_t
#if 0
// at some future point we can do this...
// TODO cleanup: at some future point we can do this:
#define off_t DO_NOT_USE_off_t
#else
#define off_t upx_off_t
@@ -203,10 +174,12 @@ typedef upx_int64_t upx_off_t;
#else
#define noinline __acc_noinline
#endif
#define forceinline_constexpr forceinline constexpr
#define likely __acc_likely
#define unlikely __acc_unlikely
#define very_likely __acc_very_likely
#define very_unlikely __acc_very_unlikely
#define may_throw noexcept(false)
#define COMPILE_TIME_ASSERT(e) ACC_COMPILE_TIME_ASSERT(e)
#define DELETED_FUNCTION = delete
@@ -226,13 +199,20 @@ typedef upx_int64_t upx_off_t;
#undef small
#undef tos
#undef unix
#if defined(__linux__) && !defined(__unix__)
#if (ACC_OS_POSIX) && !defined(__unix__)
# define __unix__ 1
#endif
#if (ACC_OS_CYGWIN || ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_EMX || ACC_OS_OS2 || ACC_OS_OS216 || ACC_OS_WIN16 || ACC_OS_WIN32 || ACC_OS_WIN64)
# undef __unix
# undef __unix__
#endif
#if (ACC_OS_DOS32) && defined(__DJGPP__)
# undef sopen
# undef __unix__
# undef __unix
#endif
#if defined(HAVE_DUP) && (HAVE_DUP + 0 == 0)
# undef dup
# define dup(x) (-1)
#endif
#ifndef STDIN_FILENO
@@ -291,7 +271,7 @@ typedef upx_int64_t upx_off_t;
# endif
#endif
// avoid warnings about shadowing global functions
// avoid warnings about shadowing global symbols
#undef _base
#undef basename
#undef index
@@ -345,14 +325,11 @@ typedef upx_int64_t upx_off_t;
# define attribute_format(a,b) /*empty*/
#endif
inline void NO_printf(const char *, ...) attribute_format(1, 2);
inline void NO_fprintf(FILE *, const char *, ...) attribute_format(2, 3);
inline void NO_printf(const char *, ...) {}
inline void NO_fprintf(FILE *, const char *, ...) {}
#if !defined(__has_builtin)
# define __has_builtin(x) 0
#endif
// for no-op debug output
inline void NO_printf(const char *, ...) noexcept attribute_format(1, 2);
inline void NO_fprintf(FILE *, const char *, ...) noexcept attribute_format(2, 3);
inline void NO_printf(const char *, ...) noexcept {}
inline void NO_fprintf(FILE *, const char *, ...) noexcept {}
#if __has_builtin(__builtin_memcpy_inline)
# define upx_memcpy_inline __builtin_memcpy_inline
@@ -374,18 +351,10 @@ inline void NO_fprintf(FILE *, const char *, ...) {}
# define upx_return_address() nullptr
#endif
// TODO cleanup: we now require C++14, so remove all __packed_struct usage
// TODO cleanup: we now require C++17, so remove all __packed_struct usage
#define __packed_struct(s) struct alignas(1) s {
#define __packed_struct_end() };
#if (ACC_ARCH_M68K && ACC_OS_TOS && ACC_CC_GNUC) && defined(__MINT__)
// horrible hack for broken compiler
#define upx_fake_alignas_1 __attribute__((__aligned__(1),__packed__))
#define upx_fake_alignas_16 __attribute__((__aligned__(2))) // object file maximum 2 ???
#define upx_fake_alignas__(a) upx_fake_alignas_ ## a
#define alignas(x) upx_fake_alignas__(x)
#endif
#define COMPILE_TIME_ASSERT_ALIGNOF_USING_SIZEOF__(a,b) { \
typedef a acc_tmp_a_t; typedef b acc_tmp_b_t; \
struct alignas(1) acc_tmp_t { acc_tmp_b_t x; acc_tmp_a_t y; acc_tmp_b_t z; }; \
@@ -413,62 +382,55 @@ inline const T& UPX_MAX(const T& a, const T& b) { if (a < b) return b; return a;
template <class T>
inline const T& UPX_MIN(const T& a, const T& b) { if (a < b) return a; return b; }
template <size_t TypeSize>
struct USizeOfTypeImpl {
static forceinline constexpr unsigned value() {
COMPILE_TIME_ASSERT(TypeSize >= 1 && TypeSize <= 64 * 1024); // arbitrary limit
return ACC_ICONV(unsigned, TypeSize);
}
};
#define usizeof(type) (USizeOfTypeImpl<sizeof(type)>::value())
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(int) == 4)
template <class T>
inline void mem_clear(T *object) noexcept {
static_assert(std::is_class_v<T>); // UPX convention
static_assert(std::is_standard_layout_v<T>);
static_assert(std::is_trivially_copyable_v<T>);
constexpr size_t size = sizeof(*object);
static_assert(size >= 1 && size <= UPX_RSIZE_MAX_MEM);
memset((void *) object, 0, size);
}
#if defined(__clang__) || __GNUC__ != 7
template <class T>
inline void mem_clear(T (&array)[]) noexcept DELETED_FUNCTION;
#endif
template <class T, size_t N>
inline void mem_clear(T (&array)[N]) noexcept DELETED_FUNCTION;
// An Array allocates memory on the heap, and automatically
// gets destructed when leaving scope or on exceptions.
#define Array(type, var, size) \
MemBuffer var ## _membuf(mem_size(sizeof(type), size)); \
#define Array(type, var, n) \
MemBuffer var ## _membuf(mem_size(sizeof(type), (n))); \
type * const var = ACC_STATIC_CAST(type *, var ## _membuf.getVoidPtr())
#define ByteArray(var, size) Array(unsigned char, var, size)
#define ByteArray(var, n) Array(byte, var, (n))
// assert_noexcept()
noinline void assertFailed(const char *expr, const char *file, int line, const char *func) noexcept;
noinline void throwAssertFailed(const char *expr, const char *file, int line, const char *func);
#if defined(__GNUC__)
#undef assert
#if DEBUG || 0
// generate a warning if assert() is used inside a "noexcept" context
#define assert(e) ((void)(__acc_cte(e) || (assertFailed(#e, __FILE__, __LINE__, __func__), throw 1, 0)))
#else
// turn assertion failures into exceptions
#define assert(e) ((void)(__acc_cte(e) || (throwAssertFailed(#e, __FILE__, __LINE__, __func__), throw 1, 0)))
#endif
#define assert_noexcept(e) ((void)(__acc_cte(e) || (assertFailed(#e, __FILE__, __LINE__, __func__), 0)))
#else
#define assert_noexcept assert
#endif
class noncopyable
{
protected:
inline noncopyable() {}
inline ~noncopyable() {}
private:
noncopyable(const noncopyable &) DELETED_FUNCTION; // copy constuctor
noncopyable& operator=(const noncopyable &) DELETED_FUNCTION; // copy assignment
noncopyable(noncopyable &&) DELETED_FUNCTION; // move constructor
noncopyable& operator=(noncopyable &&) DELETED_FUNCTION; // move assignment
};
#include "util/cxxlib.h"
using upx::is_same_any_v;
using upx::noncopyable;
using upx::tribool;
using upx::OptVar;
#define usizeof(expr) (upx::UnsignedSizeOf<sizeof(expr)>::value)
namespace compile_time {
constexpr size_t string_len(const char *a) {
return *a == '\0' ? 0 : 1 + string_len(a + 1);
}
constexpr bool string_eq(const char *a, const char *b) {
return *a == *b && (*a == '\0' || string_eq(a + 1, b + 1));
}
constexpr bool string_lt(const char *a, const char *b) {
return (unsigned char)*a < (unsigned char)*b || (*a != '\0' && *a == *b && string_lt(a + 1, b + 1));
}
constexpr bool string_ne(const char *a, const char *b) {
return !string_eq(a, b);
}
constexpr bool string_gt(const char *a, const char *b) {
return string_lt(b, a);
}
constexpr bool string_le(const char *a, const char *b) {
return !string_lt(b, a);
}
constexpr bool string_ge(const char *a, const char *b) {
return !string_lt(a, b);
}
}
/*************************************************************************
// constants
**************************************************************************/
@@ -506,7 +468,7 @@ constexpr bool string_ge(const char *a, const char *b) {
#define UPX_E_INVALID_ARGUMENT (-10)
// Executable formats. Note: big endian types are >= 128.
// Executable formats (info: big endian types are >= 128); DO NOT CHANGE
#define UPX_F_DOS_COM 1
#define UPX_F_DOS_SYS 2
#define UPX_F_DOS_EXE 3
@@ -515,7 +477,7 @@ constexpr bool string_ge(const char *a, const char *b) {
//#define UPX_F_VXD_LE 6 // NOT IMPLEMENTED
#define UPX_F_DOS_EXEH 7 // OBSOLETE
#define UPX_F_TMT_ADAM 8
#define UPX_F_WIN32_PE 9
#define UPX_F_W32PE_I386 9
#define UPX_F_LINUX_i386 10
//#define UPX_F_WIN16_NE 11 // NOT IMPLEMENTED
#define UPX_F_LINUX_ELF_i386 12
@@ -527,52 +489,47 @@ constexpr bool string_ge(const char *a, const char *b) {
#define UPX_F_PS1_EXE 18
#define UPX_F_VMLINUX_i386 19
#define UPX_F_LINUX_ELFI_i386 20
#define UPX_F_WINCE_ARM_PE 21
#define UPX_F_LINUX_ELF64_AMD 22
#define UPX_F_LINUX_ELF32_ARMEL 23
#define UPX_F_WINCE_ARM 21 // Windows CE
#define UPX_F_LINUX_ELF64_AMD64 22
#define UPX_F_LINUX_ELF32_ARM 23
#define UPX_F_BSD_i386 24
#define UPX_F_BSD_ELF_i386 25
#define UPX_F_BSD_SH_i386 26
#define UPX_F_VMLINUX_AMD64 27
#define UPX_F_VMLINUX_ARMEL 28
#define UPX_F_VMLINUX_ARM 28
#define UPX_F_MACH_i386 29
#define UPX_F_LINUX_ELF32_MIPSEL 30
#define UPX_F_VMLINUZ_ARMEL 31
#define UPX_F_MACH_ARMEL 32
#define UPX_F_VMLINUZ_ARM 31
#define UPX_F_MACH_ARM 32
#define UPX_F_DYLIB_i386 33
#define UPX_F_MACH_AMD64 34
#define UPX_F_DYLIB_AMD64 35
#define UPX_F_WIN64_PEP 36
#define UPX_F_MACH_ARM64EL 37
//#define UPX_F_MACH_PPC64LE 38 // DOES NOT EXIST
#define UPX_F_LINUX_ELFPPC64LE 39
#define UPX_F_W64PE_AMD64 36
#define UPX_F_MACH_ARM64 37
//#define UPX_F_MACH_PPC64LE 38 // DOES NOT EXIST
#define UPX_F_LINUX_ELF64_PPC64LE 39
#define UPX_F_VMLINUX_PPC64LE 40
//#define UPX_F_DYLIB_PPC64LE 41 // DOES NOT EXIST
#define UPX_F_LINUX_ELF64_ARM 42
//#define UPX_F_DYLIB_PPC64LE 41 // DOES NOT EXIST
#define UPX_F_LINUX_ELF64_ARM64 42
#define UPX_F_W64PE_ARM64 43 // NOT YET IMPLEMENTED
#define UPX_F_W64PE_ARM64EC 44 // NOT YET IMPLEMENTED
#define UPX_F_ATARI_TOS 129
//#define UPX_F_SOLARIS_SPARC 130 // NOT IMPLEMENTED
#define UPX_F_MACH_PPC32 131
#define UPX_F_LINUX_ELFPPC32 132
#define UPX_F_LINUX_ELF32_PPC32 132
#define UPX_F_LINUX_ELF32_ARMEB 133
#define UPX_F_MACH_FAT 134
#define UPX_F_VMLINUX_ARMEB 135
#define UPX_F_VMLINUX_PPC32 136
#define UPX_F_LINUX_ELF32_MIPSEB 137
#define UPX_F_LINUX_ELF32_MIPS 137
#define UPX_F_DYLIB_PPC32 138
#define UPX_F_MACH_PPC64 139
#define UPX_F_LINUX_ELFPPC64 140
#define UPX_F_LINUX_ELF64_PPC64 140
#define UPX_F_VMLINUX_PPC64 141
#define UPX_F_DYLIB_PPC64 142
// compression methods - DO NOT CHANGE
// compression methods; DO NOT CHANGE
#define M_NRV2B_LE32 2
#define M_NRV2B_8 3
#define M_NRV2B_LE16 4
@@ -604,7 +561,7 @@ constexpr bool string_ge(const char *a, const char *b) {
#define M_IS_ZSTD(x) ((x) == M_ZSTD)
// filters
// filters internal usage
#define FT_END (-1)
#define FT_NONE (-2)
#define FT_SKIP (-3)
@@ -631,12 +588,11 @@ typedef upx_callback_t *upx_callback_p;
typedef void (__acc_cdecl *upx_progress_func_t)
(upx_callback_p, unsigned, unsigned);
struct upx_callback_t
{
struct upx_callback_t {
upx_progress_func_t nprogress;
void *user;
void reset() { memset(this, 0, sizeof(*this)); }
void reset() noexcept { mem_clear(this); }
};
@@ -644,53 +600,7 @@ struct upx_callback_t
// compression - config_t
**************************************************************************/
template <class T, T default_value_, T min_value_, T max_value_>
struct OptVar
{
typedef T value_type;
static const T default_value = default_value_;
static const T min_value = min_value_;
static const T max_value = max_value_;
static void assertValue(const T &v) {
// info: this generates annoying warnings "unsigned >= 0 is always true"
//assert(v >= min_value);
assert(v == min_value || v >= min_value + 1);
assert(v <= max_value);
}
void assertValue() const {
assertValue(v);
}
OptVar() : v(default_value), is_set(false) { }
OptVar& operator= (const T &other) {
assertValue(other);
v = other;
is_set = true;
return *this;
}
void reset() { v = default_value; is_set = false; }
operator T () const { return v; }
T v;
bool is_set;
};
// optional assignments
template <class T, T a, T b, T c>
inline void oassign(OptVar<T,a,b,c> &self, const OptVar<T,a,b,c> &other) {
if (other.is_set) { self.v = other.v; self.is_set = true; }
}
template <class T, T a, T b, T c>
inline void oassign(T &v, const OptVar<T,a,b,c> &other) {
if (other.is_set) { v = other.v; }
}
struct lzma_compress_config_t
{
struct lzma_compress_config_t {
typedef OptVar<unsigned, 2u, 0u, 4u> pos_bits_t; // pb
typedef OptVar<unsigned, 0u, 0u, 4u> lit_pos_bits_t; // lp
typedef OptVar<unsigned, 3u, 0u, 8u> lit_context_bits_t; // lc
@@ -707,16 +617,14 @@ struct lzma_compress_config_t
unsigned max_num_probs;
void reset();
void reset() noexcept;
};
struct ucl_compress_config_t : public REAL_ucl_compress_config_t
{
void reset() { memset(this, 0xff, sizeof(*this)); }
struct ucl_compress_config_t : public REAL_ucl_compress_config_t {
void reset() noexcept { memset(this, 0xff, sizeof(*this)); }
};
struct zlib_compress_config_t
{
struct zlib_compress_config_t {
typedef OptVar<unsigned, 8u, 1u, 9u> mem_level_t; // ml
typedef OptVar<unsigned, 15u, 9u, 15u> window_bits_t; // wb
typedef OptVar<unsigned, 0u, 0u, 4u> strategy_t; // st
@@ -725,23 +633,22 @@ struct zlib_compress_config_t
window_bits_t window_bits; // wb
strategy_t strategy; // st
void reset();
void reset() noexcept;
};
struct zstd_compress_config_t
{
struct zstd_compress_config_t {
unsigned dummy;
void reset();
void reset() noexcept;
};
struct upx_compress_config_t
{
struct upx_compress_config_t {
lzma_compress_config_t conf_lzma;
ucl_compress_config_t conf_ucl;
zlib_compress_config_t conf_zlib;
zstd_compress_config_t conf_zstd;
void reset() { conf_lzma.reset(); conf_ucl.reset(); conf_zlib.reset(); conf_zstd.reset(); }
void reset() noexcept { conf_lzma.reset(); conf_ucl.reset(); conf_zlib.reset(); conf_zstd.reset(); }
};
#define NULL_cconf ((upx_compress_config_t *) nullptr)
@@ -751,8 +658,7 @@ struct upx_compress_config_t
// compression - result_t
**************************************************************************/
struct lzma_compress_result_t
{
struct lzma_compress_result_t {
unsigned pos_bits; // pb
unsigned lit_pos_bits; // lp
unsigned lit_context_bits; // lc
@@ -762,45 +668,43 @@ struct lzma_compress_result_t
unsigned match_finder_cycles;
unsigned num_probs; // (computed result)
void reset() { memset(this, 0, sizeof(*this)); }
void reset() noexcept { mem_clear(this); }
};
struct ucl_compress_result_t
{
struct ucl_compress_result_t {
ucl_uint result[16];
void reset() { memset(this, 0, sizeof(*this)); }
void reset() noexcept { mem_clear(this); }
};
struct zlib_compress_result_t
{
struct zlib_compress_result_t {
unsigned dummy;
void reset() { memset(this, 0, sizeof(*this)); }
void reset() noexcept { mem_clear(this); }
};
struct zstd_compress_result_t
{
struct zstd_compress_result_t {
unsigned dummy;
void reset() { memset(this, 0, sizeof(*this)); }
void reset() noexcept { mem_clear(this); }
};
struct upx_compress_result_t
{
struct upx_compress_result_t {
// debugging aid
struct {
struct Debug {
int method, level;
unsigned u_len, c_len;
} debug;
void reset() noexcept { mem_clear(this); }
};
Debug debug;
lzma_compress_result_t result_lzma;
ucl_compress_result_t result_ucl;
zlib_compress_result_t result_zlib;
zstd_compress_result_t result_zstd;
void reset() {
memset(&this->debug, 0, sizeof(this->debug));
void reset() noexcept {
debug.reset();
result_lzma.reset(); result_ucl.reset(); result_zlib.reset(); result_zstd.reset();
}
};
@@ -810,60 +714,52 @@ struct upx_compress_result_t
// globals
**************************************************************************/
#include "util/snprintf.h" // must get included first!
#include "options.h"
#include "except.h"
#include "bele.h"
#include "console/console.h"
#include "util/util.h"
// classes
class ElfLinker;
typedef ElfLinker Linker;
class Throwable;
// util/membuffer.h
class MemBuffer;
void *membuffer_get_void_ptr(MemBuffer &mb);
unsigned membuffer_get_size(MemBuffer &mb);
// xspan
#include "util/xspan.h"
void *membuffer_get_void_ptr(MemBuffer &mb) noexcept;
unsigned membuffer_get_size(MemBuffer &mb) noexcept;
// util/dt_check.cpp
void upx_compiler_sanity_check();
noinline void upx_compiler_sanity_check() noexcept;
noinline int upx_doctest_check(int argc, char **argv);
int upx_doctest_check();
int upx_doctest_check(int argc, char **argv);
// main.cpp
extern const char *progname;
bool main_set_exit_code(int ec);
int main_get_options(int argc, char **argv);
void main_get_envoptions();
int upx_main(int argc, char *argv[]);
int upx_main(int argc, char *argv[]) may_throw;
// msg.cpp
void printSetNl(int need_nl);
void printClearLine(FILE *f = nullptr);
void printErr(const char *iname, const Throwable *e);
void printUnhandledException(const char *iname, const std::exception *e);
void printErr(const char *iname, const char *format, ...) attribute_format(2, 3);
void printWarn(const char *iname, const char *format, ...) attribute_format(2, 3);
void printSetNl(int need_nl) noexcept;
void printClearLine(FILE *f = nullptr) noexcept;
void printErr(const char *iname, const Throwable &e) noexcept;
void printUnhandledException(const char *iname, const std::exception *e) noexcept;
void printErr(const char *iname, const char *format, ...) noexcept attribute_format(2, 3);
void printWarn(const char *iname, const char *format, ...) noexcept attribute_format(2, 3);
void infoWarning(const char *format, ...) attribute_format(1, 2);
void infoHeader(const char *format, ...) attribute_format(1, 2);
void info(const char *format, ...) attribute_format(1, 2);
void infoHeader();
void infoWriting(const char *what, long size);
void infoWriting(const char *what, upx_int64_t size);
// work.cpp
void do_one_file(const char *iname, char *oname);
int do_files(int i, int argc, char *argv[]);
void do_one_file(const char *iname, char *oname) may_throw;
int do_files(int i, int argc, char *argv[]) may_throw;
// help.cpp
extern const char gitrev[];
void show_head();
void show_header();
void show_help(int verbose=0);
void show_license();
void show_sysinfo(const char *options_var);
void show_usage();
void show_version(bool one_line=false);
@@ -871,6 +767,7 @@ void show_version(bool one_line=false);
unsigned upx_adler32(const void *buf, unsigned len, unsigned adler=1);
unsigned upx_crc32 (const void *buf, unsigned len, unsigned crc=0);
// clang-format off
int upx_compress ( const upx_bytep src, unsigned src_len,
upx_bytep dst, unsigned* dst_len,
upx_callback_p cb,
@@ -887,14 +784,18 @@ int upx_test_overlap ( const upx_bytep buf,
unsigned* dst_len,
int method,
const upx_compress_result_t *cresult );
// clang-format on
#if (ACC_OS_CYGWIN || ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_EMX || ACC_OS_OS2 || ACC_OS_OS216 || ACC_OS_WIN16 || ACC_OS_WIN32 || ACC_OS_WIN64)
# if defined(INVALID_HANDLE_VALUE) || defined(MAKEWORD) || defined(RT_CURSOR)
# error "something pulled in <windows.h>"
# endif
#endif
#include "util/snprintf.h" // must get included first!
#include "util/util.h"
#include "options.h"
#include "except.h"
#include "bele.h"
#include "console/console.h"
// xspan
#include "util/raw_bytes.h"
#include "util/xspan.h"
#endif /* already included */
/* vim:set ts=4 sw=4 et: */
+25 -25
View File
@@ -44,7 +44,7 @@
#endif
#if 1 && defined(__linux__)
#define USE_SCREEN 1
#define USE_SCREEN 1
#define USE_SCREEN_VCSA 1
#if !(HAVE_LINUX_KD_H)
#undef USE_SCREEN
@@ -59,10 +59,10 @@
#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 1
#define USE_SCREEN 1
#define USE_SCREEN_WIN32 1
#elif 1 && (ACC_OS_EMX && defined(__RSXNT__))
#define USE_SCREEN 1
#define USE_SCREEN 1
#define USE_SCREEN_WIN32 1
#elif 1 && (ACC_ARCH_M68K && ACC_OS_TOS)
#define NO_CONSOLE 1
@@ -111,31 +111,31 @@ typedef struct {
void con_fprintf(FILE *f, const char *format, ...) attribute_format(2, 3);
#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_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_WHITE 0x70
#endif /* USE_CONSOLE */
@@ -162,7 +162,7 @@ extern console_t console_screen;
#else
#define con_fg(f, x) 0
#define con_fprintf fprintf
#define con_fprintf fprintf
#endif /* USE_CONSOLE */
+1 -1
View File
@@ -55,7 +55,7 @@
#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 co80 _go32_info_block.linear_address_of_primary_screen
#undef kbhit
#define Cell upx_uint16_t
+25 -18
View File
@@ -29,6 +29,15 @@
#if (USE_SCREEN_WIN32)
/*************************************************************************
// direct screen access
**************************************************************************/
#include "../util/windows_lean.h"
#if (HAVE_CONIO_H)
#include <conio.h>
#endif
#include "screen.h"
#define this self
@@ -36,24 +45,6 @@
#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)
#endif
#if defined(__RSXNT__)
#define timeval win32_timeval /* struct timeval already in <sys/time.h> */
#endif
#include <windows.h>
#if (HAVE_CONIO_H)
#include <conio.h>
#endif
struct screen_data_t {
HANDLE hi;
HANDLE ho;
@@ -266,6 +257,22 @@ static int init(screen_t *this, int fd) {
#endif
#endif
#if 1
// check if we are running under Wine
// (this rather direct Win32 screen driver maps poorly to Unix terminals)
// ntdll.dll wine_get_version() was added in wine-0.9.59 (Apr 2008)
HMODULE ntdll = GetModuleHandleA("ntdll.dll");
if (ntdll != nullptr) {
typedef const char *(CDECL * wine_get_version_func_t)(void);
wine_get_version_func_t wine_get_version;
wine_get_version =
(wine_get_version_func_t) (void *) GetProcAddress(ntdll, "wine_get_version");
if (wine_get_version != nullptr) {
return -1;
}
}
#endif
this->data->cursor_x = csbi->dwCursorPosition.X;
this->data->cursor_y = csbi->dwCursorPosition.Y;
-4
View File
@@ -26,8 +26,6 @@
*/
#pragma once
#ifndef UPX_SCREEN_H__
#define UPX_SCREEN_H__ 1
#if (USE_SCREEN)
@@ -100,6 +98,4 @@ void screen_show_frames(screen_t *);
#endif /* USE_SCREEN */
#endif /* already included */
/* vim:set ts=4 sw=4 et: */
+50 -10
View File
@@ -31,7 +31,7 @@
//
**************************************************************************/
unsigned long Throwable::counter = 0;
/*static*/ upx_std_atomic(size_t) Throwable::debug_counter;
Throwable::Throwable(const char *m, int e, bool w) noexcept : super(),
msg(nullptr),
@@ -40,8 +40,8 @@ Throwable::Throwable(const char *m, int e, bool w) noexcept : super(),
if (m)
msg = strdup(m);
#if 0
fprintf(stderr, "construct exception: %s %lu\n", msg, counter);
counter++;
fprintf(stderr, "construct exception: %s %zu\n", msg, debug_counter);
debug_counter += 1;
#endif
}
@@ -52,15 +52,15 @@ Throwable::Throwable(const Throwable &other) noexcept : super(other),
if (other.msg)
msg = strdup(other.msg);
#if 0
fprintf(stderr, "copy exception: %s %lu\n", msg, counter);
counter++;
fprintf(stderr, "copy exception: %s %zu\n", msg, debug_counter);
debug_counter += 1;
#endif
}
Throwable::~Throwable() noexcept {
#if 0
counter--;
fprintf(stderr, "destruct exception: %s %lu\n", msg, counter);
debug_counter -= 1;
fprintf(stderr, "destruct exception: %s %zu\n", msg, debug_counter);
#endif
if (msg)
free(msg);
@@ -72,7 +72,9 @@ Throwable::~Throwable() noexcept {
void throwCantPack(const char *msg) {
// UGLY, but makes things easier
if (opt->cmd == CMD_COMPRESS)
if (opt->cmd == CMD_NONE)
throw CantPackException(msg);
else if (opt->cmd == CMD_COMPRESS)
throw CantPackException(msg);
else if (opt->cmd == CMD_FILEINFO)
throw CantPackException(msg);
@@ -140,9 +142,47 @@ void throwEOFException(const char *msg, int e) {
}
/*************************************************************************
//
// varargs overloads
**************************************************************************/
template <>
void throwCantPack(const char *format, ...) {
char msg[1024];
va_list ap;
va_start(ap, format);
(void) upx_safe_vsnprintf(msg, sizeof(msg), format, ap);
va_end(ap);
throwCantPack(msg);
}
template <>
void throwCantUnpack(const char *format, ...) {
char msg[1024];
va_list ap;
va_start(ap, format);
(void) upx_safe_vsnprintf(msg, sizeof(msg), format, ap);
va_end(ap);
throwCantUnpack(msg);
}
/*************************************************************************
// util
**************************************************************************/
void assertFailed(const char *expr, const char *file, int line, const char *func) noexcept {
fflush(stdout);
fprintf(stderr, "Assertion failed: %s (%s: %s: %d)\n", expr, file, func, line);
std::terminate();
}
void throwAssertFailed(const char *expr, const char *file, int line, const char *func) {
if (opt->debug.debug_level >= 1) {
throwCantPack("corrupted file; details: %s (%s: %s: %d)", expr, file, func, line);
} else {
throwCantPack("corrupted file; try '--debug' for more details");
}
}
const char *prettyName(const char *n) noexcept {
if (n == nullptr)
return "(null)";
@@ -151,7 +191,7 @@ const char *prettyName(const char *n) noexcept {
n++;
else if (*n == ' ')
n++;
else if (strncmp(n, "class ", 6) == 0) // Visual C++
else if (strncmp(n, "class ", 6) == 0) // Visual C++ (msvc)
n += 6;
else
break;
+51 -57
View File
@@ -26,13 +26,12 @@
*/
#pragma once
#ifndef UPX_EXCEPT_H__
#define UPX_EXCEPT_H__ 1
#ifdef __cplusplus
const char *prettyName(const char *n) noexcept;
noinline void assertFailed(const char *expr, const char *file, int line, const char *func) noexcept;
noinline void throwAssertFailed(const char *expr, const char *file, int line, const char *func);
/*************************************************************************
// exceptions
**************************************************************************/
@@ -53,24 +52,27 @@ public:
private:
char *msg = nullptr;
int err = 0;
protected:
bool is_warning = false; // can be set by subclasses
private:
// disable assignment
Throwable &operator=(const Throwable &) = delete;
// disable copy assignment and move
Throwable &operator=(const Throwable &) DELETED_FUNCTION;
Throwable(Throwable &&) noexcept DELETED_FUNCTION;
Throwable &operator=(Throwable &&) noexcept DELETED_FUNCTION;
// disable dynamic allocation => force throwing by value
ACC_CXX_DISABLE_NEW_DELETE
// disable taking the address => force passing by reference
// [I'm not too sure about this design decision, but we can always allow it if needed]
Throwable *operator&() const noexcept DELETED_FUNCTION;
private:
static unsigned long counter; // for debugging
static upx_std_atomic(size_t) debug_counter; // for debugging
};
// Exceptions can/should be caught
class Exception : public Throwable {
typedef Throwable super;
public:
Exception(const char *m = nullptr, int e = 0, bool w = false) noexcept : super(m, e, w) {}
};
@@ -78,7 +80,6 @@ public:
// Errors should not be caught (or re-thrown)
class Error : public Throwable {
typedef Throwable super;
public:
Error(const char *m = nullptr, int e = 0) noexcept : super(m, e) {}
};
@@ -87,37 +88,32 @@ public:
// system exception
**************************************************************************/
class OutOfMemoryException : public Exception {
class OutOfMemoryException final : public Exception {
typedef Exception super;
public:
OutOfMemoryException(const char *m = nullptr, int e = 0) noexcept : super(m, e) {}
};
class IOException : public Exception {
class IOException /*not_final*/ : public Exception {
typedef Exception super;
public:
IOException(const char *m = nullptr, int e = 0) noexcept : super(m, e) {}
};
class EOFException : public IOException {
class EOFException final : public IOException {
typedef IOException super;
public:
EOFException(const char *m = nullptr, int e = 0) noexcept : super(m, e) {}
};
class FileNotFoundException : public IOException {
class FileNotFoundException final : public IOException {
typedef IOException super;
public:
FileNotFoundException(const char *m = nullptr, int e = 0) noexcept : super(m, e) {}
};
class FileAlreadyExistsException : public IOException {
class FileAlreadyExistsException final : public IOException {
typedef IOException super;
public:
FileAlreadyExistsException(const char *m = nullptr, int e = 0) noexcept : super(m, e) {}
};
@@ -126,52 +122,45 @@ public:
// application exceptions
**************************************************************************/
class OverlayException : public Exception {
class OverlayException final : public Exception {
typedef Exception super;
public:
OverlayException(const char *m = nullptr, bool w = false) noexcept : super(m, 0, w) {}
};
class CantPackException : public Exception {
class CantPackException /*not_final*/ : public Exception {
typedef Exception super;
public:
CantPackException(const char *m = nullptr, bool w = false) noexcept : super(m, 0, w) {}
};
class UnknownExecutableFormatException : public CantPackException {
typedef CantPackException super;
public:
UnknownExecutableFormatException(const char *m = nullptr, bool w = false) noexcept
: super(m, w) {}
};
class AlreadyPackedException : public CantPackException {
class AlreadyPackedException final : public CantPackException {
typedef CantPackException super;
public:
AlreadyPackedException(const char *m = nullptr) noexcept : super(m) { is_warning = true; }
};
class NotCompressibleException : public CantPackException {
class NotCompressibleException final : public CantPackException {
typedef CantPackException super;
public:
NotCompressibleException(const char *m = nullptr) noexcept : super(m) {}
};
class CantUnpackException : public Exception {
class CantUnpackException /*not_final*/ : public Exception {
typedef Exception super;
public:
CantUnpackException(const char *m = nullptr, bool w = false) noexcept : super(m, 0, w) {}
};
class NotPackedException : public CantUnpackException {
class NotPackedException final : public CantUnpackException {
typedef CantUnpackException super;
public:
NotPackedException(const char *m = nullptr) noexcept : super(m, true) {}
};
@@ -180,9 +169,8 @@ public:
// errors
**************************************************************************/
class InternalError : public Error {
class InternalError final : public Error {
typedef Error super;
public:
InternalError(const char *m = nullptr) noexcept : super(m, 0) {}
};
@@ -193,32 +181,38 @@ public:
#undef NORET
#if 1 && defined(__GNUC__)
#define NORET __acc_noinline __attribute__((__noreturn__))
#define NORET noinline __attribute__((__noreturn__))
#else
#define NORET __acc_noinline
#define NORET noinline
#endif
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);
NORET void throwCantPack(const char *msg) may_throw;
NORET void throwCantPackExact() may_throw;
NORET void throwUnknownExecutableFormat(const char *msg = nullptr, bool warn = false) may_throw;
NORET void throwNotCompressible(const char *msg = nullptr) may_throw;
NORET void throwAlreadyPacked(const char *msg = nullptr) may_throw;
NORET void throwAlreadyPackedByUPX(const char *msg = nullptr) may_throw;
NORET void throwCantUnpack(const char *msg) may_throw;
NORET void throwNotPacked(const char *msg = nullptr) may_throw;
NORET void throwFilterException() may_throw;
NORET void throwBadLoader() may_throw;
NORET void throwChecksumError() may_throw;
NORET void throwCompressedDataViolation() may_throw;
NORET void throwInternalError(const char *msg) may_throw;
NORET void throwOutOfMemoryException(const char *msg = nullptr) may_throw;
NORET void throwIOException(const char *msg = nullptr, int e = 0) may_throw;
NORET void throwEOFException(const char *msg = nullptr, int e = 0) may_throw;
// some C++ template wizardry is needed to overload throwCantPack() for varargs
template <class T>
void throwCantPack(const T *, ...) DELETED_FUNCTION;
template <>
NORET void throwCantPack(const char *format, ...) may_throw attribute_format(1, 2);
template <class T>
void throwCantUnpack(const T *, ...) DELETED_FUNCTION;
template <>
NORET void throwCantUnpack(const char *format, ...) may_throw attribute_format(1, 2);
#undef NORET
#endif /* __cplusplus */
#endif /* already included */
/* vim:set ts=4 sw=4 et: */
+81 -53
View File
@@ -29,11 +29,12 @@
#include "file.h"
/*************************************************************************
// static functions
// static file-related util functions; will throw on error
**************************************************************************/
void FileBase::chmod(const char *name, int mode) {
#if (HAVE_CHMOD)
/*static*/ void FileBase::chmod(const char *name, int mode) {
assert(name != nullptr && name[0] != 0);
#if HAVE_CHMOD
if (::chmod(name, mode) != 0)
throwIOException(name, errno);
#else
@@ -42,7 +43,7 @@ void FileBase::chmod(const char *name, int mode) {
#endif
}
void FileBase::rename(const char *old_, const char *new_) {
/*static*/ void FileBase::rename(const char *old_, const char *new_) {
#if (ACC_OS_DOS32) && defined(__DJGPP__)
if (::_rename(old_, new_) != 0)
#else
@@ -51,29 +52,34 @@ void FileBase::rename(const char *old_, const char *new_) {
throwIOException("rename error", errno);
}
void FileBase::unlink(const char *name) {
if (::unlink(name) != 0)
/*static*/ bool FileBase::unlink_noexcept(const char *name) noexcept {
assert_noexcept(name != nullptr && name[0] != 0);
bool success = ::unlink(name) == 0;
#if HAVE_CHMOD
if (!success)
success = (::chmod(name, 0666) == 0 && ::unlink(name) == 0);
#endif
return success;
}
/*static*/ void FileBase::unlink(const char *name) {
if (!unlink_noexcept(name))
throwIOException(name, errno);
}
/*************************************************************************
//
// FileBase
**************************************************************************/
FileBase::FileBase()
: _fd(-1), _flags(0), _shflags(0), _mode(0), _name(nullptr), _offset(0), _length(0) {
memset(&st, 0, sizeof(st));
}
FileBase::~FileBase() {
FileBase::~FileBase() may_throw {
#if 0 && defined(__GNUC__) // debug
if (isOpen())
fprintf(stderr,"%s: %s\n", _name, __PRETTY_FUNCTION__);
fprintf(stderr, "%s: %s\n", _name, __PRETTY_FUNCTION__);
#endif
// FIXME: we should use close() during exception unwinding but
// closex() otherwise
closex();
if (std::uncaught_exceptions() == 0)
closex(); // may_throw
else
close_noexcept(); // currently in exception unwinding, use noexcept variant
}
bool FileBase::do_sopen() {
@@ -98,7 +104,7 @@ bool FileBase::do_sopen() {
return true;
}
bool FileBase::close() {
bool FileBase::close_noexcept() noexcept {
bool ok = true;
if (isOpen() && _fd != STDIN_FILENO && _fd != STDOUT_FILENO && _fd != STDERR_FILENO)
if (::close(_fd) == -1)
@@ -112,8 +118,8 @@ bool FileBase::close() {
return ok;
}
void FileBase::closex() {
if (!close())
void FileBase::closex() may_throw {
if (!close_noexcept())
throwIOException("close failed", errno);
}
@@ -126,18 +132,18 @@ upx_off_t FileBase::seek(upx_off_t off, int whence) {
if (off < 0)
throwIOException("bad seek 2");
off += _offset;
}
if (whence == SEEK_END) {
} else if (whence == SEEK_END) {
if (off > 0)
throwIOException("bad seek 3");
off += _offset + _length;
whence = SEEK_SET;
}
// SEEK_CUR falls through to here
upx_off_t rv = ::lseek(_fd, off, whence);
if (rv < 0)
} else if (whence == SEEK_CUR) {
} else
throwInternalError("bad seek: whence");
upx_off_t l = ::lseek(_fd, off, whence);
if (l < 0)
throwIOException("seek error", errno);
return rv - _offset;
return l - _offset;
}
upx_off_t FileBase::tell() const {
@@ -157,13 +163,11 @@ void FileBase::set_extent(upx_off_t offset, upx_off_t length) {
upx_off_t FileBase::st_size() const { return _length; }
/*************************************************************************
//
// InputFile
**************************************************************************/
InputFile::InputFile() {}
void InputFile::sopen(const char *name, int flags, int shflags) {
close();
closex();
_name = name;
_flags = flags;
_shflags = shflags;
@@ -181,10 +185,10 @@ void InputFile::sopen(const char *name, int flags, int shflags) {
_length_orig = _length;
}
int InputFile::read(SPAN_P(void) buf, int len) {
if (!isOpen() || len < 0)
int InputFile::read(SPAN_P(void) buf, upx_int64_t blen) {
if (!isOpen() || blen < 0)
throwIOException("bad read");
mem_size_assert(1, len); // sanity check
int len = (int) mem_size(1, blen); // sanity check
errno = 0;
long l = acc_safe_hread(_fd, raw_bytes(buf, len), len);
if (errno)
@@ -192,9 +196,9 @@ int InputFile::read(SPAN_P(void) buf, int len) {
return (int) l;
}
int InputFile::readx(SPAN_P(void) buf, int len) {
int l = this->read(buf, len);
if (l != len)
int InputFile::readx(SPAN_P(void) buf, upx_int64_t blen) {
int l = this->read(buf, blen);
if (l != blen)
throwEOFException();
return l;
}
@@ -209,13 +213,11 @@ upx_off_t InputFile::seek(upx_off_t off, int whence) {
upx_off_t InputFile::st_size_orig() const { return _length_orig; }
/*************************************************************************
//
// OutputFile
**************************************************************************/
OutputFile::OutputFile() : bytes_written(0) {}
void OutputFile::sopen(const char *name, int flags, int shflags, int mode) {
close();
closex();
_name = name;
_flags = flags;
_shflags = shflags;
@@ -237,7 +239,7 @@ void OutputFile::sopen(const char *name, int flags, int shflags, int mode) {
}
bool OutputFile::openStdout(int flags, bool force) {
close();
closex();
int fd = STDOUT_FILENO;
if (!force && acc_isatty(fd))
return false;
@@ -253,22 +255,33 @@ bool OutputFile::openStdout(int flags, bool force) {
return true;
}
void OutputFile::write(SPAN_0(const void) buf, int len) {
if (!isOpen() || len < 0)
void OutputFile::write(SPAN_0(const void) buf, upx_int64_t blen) {
if (!isOpen() || blen < 0)
throwIOException("bad write");
// allow nullptr if len == 0
if (len == 0)
// allow nullptr if blen == 0
if (blen == 0)
return;
mem_size_assert(1, len); // sanity check
int len = (int) mem_size(1, blen); // 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);
#if WITH_XSPAN >= 2
NO_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;
#if TESTING && 0
static upx_std_atomic(bool) dumping;
if (!dumping) {
dumping = true;
char fn[64];
static int part = 0;
snprintf(fn, sizeof(fn), "upx-dump-%04d.data", part++);
OutputFile::dump(fn, buf, len);
dumping = false;
}
#endif
}
upx_off_t OutputFile::st_size() const {
@@ -319,7 +332,7 @@ upx_off_t OutputFile::seek(upx_off_t off, int whence) {
void OutputFile::set_extent(upx_off_t offset, upx_off_t length) {
super::set_extent(offset, length);
bytes_written = 0;
if (0 == offset && (upx_off_t) ~0u == length) {
if (0 == offset && 0xffffffffLL == length) { // TODO: check all callers of this method
if (::fstat(_fd, &st) != 0)
throwIOException(_name, errno);
_length = st.st_size - offset;
@@ -336,7 +349,7 @@ upx_off_t OutputFile::unset_extent() {
return _length;
}
void OutputFile::dump(const char *name, SPAN_P(const void) buf, int len, int flags) {
/*static*/ void OutputFile::dump(const char *name, SPAN_P(const void) buf, int len, int flags) {
if (flags < 0)
flags = O_CREAT | O_TRUNC;
flags |= O_WRONLY | O_BINARY;
@@ -346,4 +359,19 @@ void OutputFile::dump(const char *name, SPAN_P(const void) buf, int len, int fla
f.closex();
}
/*************************************************************************
//
**************************************************************************/
TEST_CASE("file") {
InputFile fi;
CHECK(!fi.isOpen());
CHECK(fi.getFd() == -1);
CHECK(fi.st_size() == 0);
OutputFile fo;
CHECK(!fo.isOpen());
CHECK(fo.getFd() == -1);
CHECK(fo.getBytesWritten() == 0);
}
/* vim:set ts=4 sw=4 et: */
+19 -24
View File
@@ -26,8 +26,6 @@
*/
#pragma once
#ifndef UPX_FILE_H__
#define UPX_FILE_H__ 1
/*************************************************************************
//
@@ -35,15 +33,15 @@
class FileBase {
protected:
FileBase();
virtual ~FileBase();
explicit FileBase() noexcept = default;
virtual ~FileBase() may_throw;
public:
bool close();
void closex();
bool isOpen() const { return _fd >= 0; }
int getFd() const { return _fd; }
const char *getName() const { return _name; }
bool close_noexcept() noexcept;
void closex() may_throw;
bool isOpen() const noexcept { return _fd >= 0; }
int getFd() const noexcept { return _fd; }
const char *getName() const noexcept { return _name; }
virtual upx_off_t seek(upx_off_t off, int whence);
upx_off_t tell() const;
@@ -51,10 +49,11 @@ public:
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);
// static file-related util functions; will throw on error
static void chmod(const char *name, int mode) may_throw;
static void rename(const char *old_, const char *new_) may_throw;
static void unlink(const char *name) may_throw;
static bool unlink_noexcept(const char *name) noexcept;
protected:
bool do_sopen();
@@ -78,14 +77,13 @@ class InputFile final : public FileBase {
typedef FileBase super;
public:
InputFile();
virtual ~InputFile() {}
explicit InputFile() noexcept = default;
void sopen(const char *name, int flags, int shflags);
void open(const char *name, int flags) { sopen(name, flags, -1); }
int read(SPAN_P(void) buf, int len);
int readx(SPAN_P(void) buf, int len);
int read(SPAN_P(void) buf, upx_int64_t blen);
int readx(SPAN_P(void) buf, upx_int64_t blen);
virtual upx_off_t seek(upx_off_t off, int whence) override;
upx_off_t st_size_orig() const;
@@ -102,15 +100,14 @@ class OutputFile final : public FileBase {
typedef FileBase super;
public:
OutputFile();
virtual ~OutputFile() {}
explicit OutputFile() noexcept = default;
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);
// info: allow nullptr if len == 0
void write(SPAN_0(const void) buf, int len);
// info: allow nullptr if blen == 0
void write(SPAN_0(const void) buf, upx_int64_t blen);
virtual upx_off_t seek(upx_off_t off, int whence) override;
virtual upx_off_t st_size() const override; // { return _length; }
@@ -119,7 +116,7 @@ public:
upx_off_t getBytesWritten() const { return bytes_written; }
// FIXME - these won't work when using the '--stdout' option
// FIXME - this won't work when using the '--stdout' option
void rewrite(SPAN_P(const void) buf, int len);
// util
@@ -129,6 +126,4 @@ protected:
upx_off_t bytes_written = 0;
};
#endif
/* vim:set ts=4 sw=4 et: */
+24 -20
View File
@@ -33,7 +33,7 @@
// util
**************************************************************************/
static void initFilter(Filter *f, upx_byte *buf, unsigned buf_len) {
static void initFilter(Filter *f, byte *buf, unsigned buf_len) noexcept {
f->buf = buf;
f->buf_len = buf_len;
// clear output parameters
@@ -44,38 +44,37 @@ static void initFilter(Filter *f, upx_byte *buf, unsigned buf_len) {
// get a FilterEntry
**************************************************************************/
const FilterImpl::FilterEntry *FilterImpl::getFilter(int id) {
static bool done = false;
static unsigned char filter_map[256];
/*static*/ const FilterImpl::FilterEntry *FilterImpl::getFilter(int id) {
static upx_uint8_t filter_map[256];
static upx_std_once_flag init_done;
if (!done) {
// init the filter_map[]
assert(n_filters <= 254); // as 0xff means "empty slot"
upx_std_call_once(init_done, []() noexcept {
// init the filter_map[] (using a lambda function)
assert_noexcept(n_filters <= 254); // as 0xff means "empty slot"
memset(filter_map, 0xff, sizeof(filter_map));
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);
filter_map[filter_id] = (unsigned char) i;
assert_noexcept(filter_id >= 0 && filter_id <= 255);
assert_noexcept(filter_map[filter_id] == 0xff);
filter_map[filter_id] = (upx_uint8_t) i;
}
done = true;
}
});
if (id < 0 || id > 255)
return nullptr;
unsigned index = filter_map[id];
if (index == 0xff) // empty slot
return nullptr;
assert(filters[index].id == id);
assert_noexcept(filters[index].id == id);
return &filters[index];
}
bool Filter::isValidFilter(int filter_id) {
/*static*/ 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) {
/*static*/ bool Filter::isValidFilter(int filter_id, const int *allowed_filters) {
if (!isValidFilter(filter_id))
return false;
if (filter_id == 0)
@@ -92,7 +91,9 @@ bool Filter::isValidFilter(int filter_id, const int *allowed_filters) {
// high level API
**************************************************************************/
void Filter::init(int id_, unsigned addvalue_) {
Filter::Filter(int level) noexcept : clevel(level) { init(); }
void Filter::init(int id_, unsigned addvalue_) noexcept {
this->id = id_;
initFilter(this, nullptr, 0);
// clear input parameters
@@ -103,7 +104,8 @@ void Filter::init(int id_, unsigned addvalue_) {
this->n_mru = 0;
}
bool Filter::filter(upx_byte *buf_, unsigned buf_len_) {
bool Filter::filter(SPAN_0(byte) xbuf, unsigned buf_len_) {
byte *const buf_ = raw_bytes(xbuf, buf_len_);
initFilter(this, buf_, buf_len_);
const FilterImpl::FilterEntry *const fe = FilterImpl::getFilter(id);
@@ -134,7 +136,8 @@ 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(SPAN_0(byte) xbuf, unsigned buf_len_, bool verify_checksum) {
byte *const buf_ = raw_bytes(xbuf, buf_len_);
initFilter(this, buf_, buf_len_);
const FilterImpl::FilterEntry *const fe = FilterImpl::getFilter(id);
@@ -178,10 +181,11 @@ void Filter::verifyUnfilter() {
unfilter(this->buf, this->buf_len, true);
}
bool Filter::scan(const upx_byte *buf_, unsigned buf_len_) {
bool Filter::scan(SPAN_0(const byte) xbuf, unsigned buf_len_) {
const byte *const buf_ = raw_bytes(xbuf, 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_);
byte *const b = const_cast<byte *>(buf_);
initFilter(this, b, buf_len_);
const FilterImpl::FilterEntry *const fe = FilterImpl::getFilter(id);
+11 -16
View File
@@ -26,8 +26,6 @@
*/
#pragma once
#ifndef UPX_FILTER_H__
#define UPX_FILTER_H__ 1
/*************************************************************************
// A filter is a reversible operation that modifies a given
@@ -46,18 +44,15 @@
// to absolute addresses so that the buffer compresses better.
**************************************************************************/
class Filter {
class Filter final {
public:
Filter(int level) {
clevel = level;
init();
}
void init(int id = 0, unsigned addvalue = 0);
explicit Filter(int level) noexcept;
void init(int id = 0, unsigned addvalue = 0) noexcept;
bool filter(upx_byte *buf, unsigned buf_len);
void unfilter(upx_byte *buf, unsigned buf_len, bool verify_checksum = false);
bool filter(SPAN_0(byte) buf, unsigned buf_len);
void unfilter(SPAN_0(byte) buf, unsigned buf_len, bool verify_checksum = false);
void verifyUnfilter();
bool scan(const upx_byte *buf, unsigned buf_len);
bool scan(SPAN_0(const byte) buf, unsigned buf_len);
static bool isValidFilter(int filter_id);
static bool isValidFilter(int filter_id, const int *allowed_filters);
@@ -65,7 +60,7 @@ public:
public:
// Will be set by each call to filter()/unfilter().
// Read-only afterwards.
upx_byte *buf = nullptr;
byte *buf = nullptr;
unsigned buf_len = 0;
// Checksum of the buffer before applying the filter
@@ -77,7 +72,7 @@ public:
const int *preferred_ctos = nullptr;
// Input/output parameters used by various filters
unsigned char cto; // call trick offset
byte cto; // call trick offset
// Output used by various filters. Read only.
unsigned calls;
@@ -101,10 +96,12 @@ private:
// This class is private to Filter - don't look.
**************************************************************************/
class FilterImpl {
class FilterImpl final {
friend class Filter;
private:
explicit FilterImpl() noexcept DELETED_FUNCTION;
struct FilterEntry {
int id; // 0 .. 255
unsigned min_buf_len;
@@ -123,6 +120,4 @@ private:
static const int n_filters; // number of filters[]
};
#endif /* already included */
/* vim:set ts=4 sw=4 et: */
+179 -248
View File
@@ -25,434 +25,325 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com>
*/
/*************************************************************************
// 16-bit calltrick ("naive")
**************************************************************************/
#define CT16(f, cond, addvalue, get, set) \
upx_byte *b = f->buf; \
upx_byte *b_end = b + f->buf_len - 3; \
do { \
if (cond) \
{ \
b += 1; \
unsigned a = (unsigned) (b - f->buf); \
f->lastcall = a; \
set(b, get(b) + (addvalue)); \
f->calls++; \
b += 2 - 1; \
} \
} while (++b < b_end); \
if (f->lastcall) f->lastcall += 2; \
#define CT16(f, cond, addvalue, get, set) \
byte *b = f->buf; \
byte *b_end = b + f->buf_len - 3; \
do { \
if (cond) { \
b += 1; \
unsigned a = (unsigned) (b - f->buf); \
f->lastcall = a; \
set(b, get(b) + (addvalue)); \
f->calls++; \
b += 2 - 1; \
} \
} while (++b < b_end); \
if (f->lastcall) \
f->lastcall += 2; \
return 0;
// filter: e8, e9, e8e9
static int f_ct16_e8(Filter *f)
{
CT16(f, (*b == 0xe8), a + f->addvalue, get_le16, set_le16)
}
static int f_ct16_e8(Filter *f) { CT16(f, (*b == 0xe8), a + f->addvalue, get_le16, set_le16) }
static int f_ct16_e9(Filter *f)
{
CT16(f, (*b == 0xe9), a + f->addvalue, get_le16, set_le16)
}
static int f_ct16_e9(Filter *f) { CT16(f, (*b == 0xe9), a + f->addvalue, get_le16, set_le16) }
static int f_ct16_e8e9(Filter *f)
{
static int f_ct16_e8e9(Filter *f) {
CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le16, set_le16)
}
// unfilter: e8, e9, e8e9
static int u_ct16_e8(Filter *f)
{
CT16(f, (*b == 0xe8), 0 - a - f->addvalue, get_le16, set_le16)
}
static int u_ct16_e8(Filter *f) { CT16(f, (*b == 0xe8), 0 - a - f->addvalue, get_le16, set_le16) }
static int u_ct16_e9(Filter *f)
{
CT16(f, (*b == 0xe9), 0 - a - f->addvalue, get_le16, set_le16)
}
static int u_ct16_e9(Filter *f) { CT16(f, (*b == 0xe9), 0 - a - f->addvalue, get_le16, set_le16) }
static int u_ct16_e8e9(Filter *f)
{
static int u_ct16_e8e9(Filter *f) {
CT16(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_le16, set_le16)
}
// scan: e8, e9, e8e9
static int s_ct16_e8(Filter *f)
{
CT16(f, (*b == 0xe8), a + f->addvalue, get_le16, set_dummy)
}
static int s_ct16_e8(Filter *f) { CT16(f, (*b == 0xe8), a + f->addvalue, get_le16, set_dummy) }
static int s_ct16_e9(Filter *f)
{
CT16(f, (*b == 0xe9), a + f->addvalue, get_le16, set_dummy)
}
static int s_ct16_e9(Filter *f) { CT16(f, (*b == 0xe9), a + f->addvalue, get_le16, set_dummy) }
static int s_ct16_e8e9(Filter *f)
{
static int s_ct16_e8e9(Filter *f) {
CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le16, set_dummy)
}
// filter: e8, e9, e8e9 with bswap le->be
static int f_ct16_e8_bswap_le(Filter *f)
{
static int f_ct16_e8_bswap_le(Filter *f) {
CT16(f, (*b == 0xe8), a + f->addvalue, get_le16, set_be16)
}
static int f_ct16_e9_bswap_le(Filter *f)
{
static int f_ct16_e9_bswap_le(Filter *f) {
CT16(f, (*b == 0xe9), a + f->addvalue, get_le16, set_be16)
}
static int f_ct16_e8e9_bswap_le(Filter *f)
{
static int f_ct16_e8e9_bswap_le(Filter *f) {
CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le16, set_be16)
}
// unfilter: e8, e9, e8e9 with bswap le->be
static int u_ct16_e8_bswap_le(Filter *f)
{
static int u_ct16_e8_bswap_le(Filter *f) {
CT16(f, (*b == 0xe8), 0 - a - f->addvalue, get_be16, set_le16)
}
static int u_ct16_e9_bswap_le(Filter *f)
{
static int u_ct16_e9_bswap_le(Filter *f) {
CT16(f, (*b == 0xe9), 0 - a - f->addvalue, get_be16, set_le16)
}
static int u_ct16_e8e9_bswap_le(Filter *f)
{
static int u_ct16_e8e9_bswap_le(Filter *f) {
CT16(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_be16, set_le16)
}
// scan: e8, e9, e8e9 with bswap le->be
static int s_ct16_e8_bswap_le(Filter *f)
{
static int s_ct16_e8_bswap_le(Filter *f) {
CT16(f, (*b == 0xe8), a + f->addvalue, get_be16, set_dummy)
}
static int s_ct16_e9_bswap_le(Filter *f)
{
static int s_ct16_e9_bswap_le(Filter *f) {
CT16(f, (*b == 0xe9), a + f->addvalue, get_be16, set_dummy)
}
static int s_ct16_e8e9_bswap_le(Filter *f)
{
static int s_ct16_e8e9_bswap_le(Filter *f) {
CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_be16, set_dummy)
}
// filter: e8, e9, e8e9 with bswap be->le
static int f_ct16_e8_bswap_be(Filter *f)
{
static int f_ct16_e8_bswap_be(Filter *f) {
CT16(f, (*b == 0xe8), a + f->addvalue, get_be16, set_le16)
}
static int f_ct16_e9_bswap_be(Filter *f)
{
static int f_ct16_e9_bswap_be(Filter *f) {
CT16(f, (*b == 0xe9), a + f->addvalue, get_be16, set_le16)
}
static int f_ct16_e8e9_bswap_be(Filter *f)
{
static int f_ct16_e8e9_bswap_be(Filter *f) {
CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_be16, set_le16)
}
// unfilter: e8, e9, e8e9 with bswap be->le
static int u_ct16_e8_bswap_be(Filter *f)
{
static int u_ct16_e8_bswap_be(Filter *f) {
CT16(f, (*b == 0xe8), 0 - a - f->addvalue, get_le16, set_be16)
}
static int u_ct16_e9_bswap_be(Filter *f)
{
static int u_ct16_e9_bswap_be(Filter *f) {
CT16(f, (*b == 0xe9), 0 - a - f->addvalue, get_le16, set_be16)
}
static int u_ct16_e8e9_bswap_be(Filter *f)
{
static int u_ct16_e8e9_bswap_be(Filter *f) {
CT16(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_le16, set_be16)
}
// scan: e8, e9, e8e9 with bswap be->le
static int s_ct16_e8_bswap_be(Filter *f)
{
static int s_ct16_e8_bswap_be(Filter *f) {
CT16(f, (*b == 0xe8), a + f->addvalue, get_le16, set_dummy)
}
static int s_ct16_e9_bswap_be(Filter *f)
{
static int s_ct16_e9_bswap_be(Filter *f) {
CT16(f, (*b == 0xe9), a + f->addvalue, get_le16, set_dummy)
}
static int s_ct16_e8e9_bswap_be(Filter *f)
{
static int s_ct16_e8e9_bswap_be(Filter *f) {
CT16(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le16, set_dummy)
}
#undef CT16
/*************************************************************************
// 32-bit calltrick ("naive")
**************************************************************************/
#define CT32(f, cond, addvalue, get, set) \
upx_byte *b = f->buf; \
upx_byte *b_end = b + f->buf_len - 5; \
do { \
if (cond) \
{ \
b += 1; \
unsigned a = (unsigned) (b - f->buf); \
f->lastcall = a; \
set(b, get(b) + (addvalue)); \
f->calls++; \
b += 4 - 1; \
} \
} while (++b < b_end); \
if (f->lastcall) f->lastcall += 4; \
#define CT32(f, cond, addvalue, get, set) \
byte *b = f->buf; \
byte *b_end = b + f->buf_len - 5; \
do { \
if (cond) { \
b += 1; \
unsigned a = (unsigned) (b - f->buf); \
f->lastcall = a; \
set(b, get(b) + (addvalue)); \
f->calls++; \
b += 4 - 1; \
} \
} while (++b < b_end); \
if (f->lastcall) \
f->lastcall += 4; \
return 0;
// filter: e8, e9, e8e9
static int f_ct32_e8(Filter *f)
{
CT32(f, (*b == 0xe8), a + f->addvalue, get_le32, set_le32)
}
static int f_ct32_e8(Filter *f) { CT32(f, (*b == 0xe8), a + f->addvalue, get_le32, set_le32) }
static int f_ct32_e9(Filter *f)
{
CT32(f, (*b == 0xe9), a + f->addvalue, get_le32, set_le32)
}
static int f_ct32_e9(Filter *f) { CT32(f, (*b == 0xe9), a + f->addvalue, get_le32, set_le32) }
static int f_ct32_e8e9(Filter *f)
{
static int f_ct32_e8e9(Filter *f) {
CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le32, set_le32)
}
// unfilter: e8, e9, e8e9
static int u_ct32_e8(Filter *f)
{
CT32(f, (*b == 0xe8), 0 - a - f->addvalue, get_le32, set_le32)
}
static int u_ct32_e8(Filter *f) { CT32(f, (*b == 0xe8), 0 - a - f->addvalue, get_le32, set_le32) }
static int u_ct32_e9(Filter *f)
{
CT32(f, (*b == 0xe9), 0 - a - f->addvalue, get_le32, set_le32)
}
static int u_ct32_e9(Filter *f) { CT32(f, (*b == 0xe9), 0 - a - f->addvalue, get_le32, set_le32) }
static int u_ct32_e8e9(Filter *f)
{
static int u_ct32_e8e9(Filter *f) {
CT32(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_le32, set_le32)
}
// scan: e8, e9, e8e9
static int s_ct32_e8(Filter *f)
{
CT32(f, (*b == 0xe8), a + f->addvalue, get_le32, set_dummy)
}
static int s_ct32_e8(Filter *f) { CT32(f, (*b == 0xe8), a + f->addvalue, get_le32, set_dummy) }
static int s_ct32_e9(Filter *f)
{
CT32(f, (*b == 0xe9), a + f->addvalue, get_le32, set_dummy)
}
static int s_ct32_e9(Filter *f) { CT32(f, (*b == 0xe9), a + f->addvalue, get_le32, set_dummy) }
static int s_ct32_e8e9(Filter *f)
{
static int s_ct32_e8e9(Filter *f) {
CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le32, set_dummy)
}
// filter: e8, e9, e8e9 with bswap le->be
static int f_ct32_e8_bswap_le(Filter *f)
{
static int f_ct32_e8_bswap_le(Filter *f) {
CT32(f, (*b == 0xe8), a + f->addvalue, get_le32, set_be32)
}
static int f_ct32_e9_bswap_le(Filter *f)
{
static int f_ct32_e9_bswap_le(Filter *f) {
CT32(f, (*b == 0xe9), a + f->addvalue, get_le32, set_be32)
}
static int f_ct32_e8e9_bswap_le(Filter *f)
{
static int f_ct32_e8e9_bswap_le(Filter *f) {
CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le32, set_be32)
}
// unfilter: e8, e9, e8e9 with bswap le->be
static int u_ct32_e8_bswap_le(Filter *f)
{
static int u_ct32_e8_bswap_le(Filter *f) {
CT32(f, (*b == 0xe8), 0 - a - f->addvalue, get_be32, set_le32)
}
static int u_ct32_e9_bswap_le(Filter *f)
{
static int u_ct32_e9_bswap_le(Filter *f) {
CT32(f, (*b == 0xe9), 0 - a - f->addvalue, get_be32, set_le32)
}
static int u_ct32_e8e9_bswap_le(Filter *f)
{
static int u_ct32_e8e9_bswap_le(Filter *f) {
CT32(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_be32, set_le32)
}
// scan: e8, e9, e8e9 with bswap le->be
static int s_ct32_e8_bswap_le(Filter *f)
{
static int s_ct32_e8_bswap_le(Filter *f) {
CT32(f, (*b == 0xe8), a + f->addvalue, get_be32, set_dummy)
}
static int s_ct32_e9_bswap_le(Filter *f)
{
static int s_ct32_e9_bswap_le(Filter *f) {
CT32(f, (*b == 0xe9), a + f->addvalue, get_be32, set_dummy)
}
static int s_ct32_e8e9_bswap_le(Filter *f)
{
static int s_ct32_e8e9_bswap_le(Filter *f) {
CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_be32, set_dummy)
}
// filter: e8, e9, e8e9 with bswap be->le
static int f_ct32_e8_bswap_be(Filter *f)
{
static int f_ct32_e8_bswap_be(Filter *f) {
CT32(f, (*b == 0xe8), a + f->addvalue, get_be32, set_le32)
}
static int f_ct32_e9_bswap_be(Filter *f)
{
static int f_ct32_e9_bswap_be(Filter *f) {
CT32(f, (*b == 0xe9), a + f->addvalue, get_be32, set_le32)
}
static int f_ct32_e8e9_bswap_be(Filter *f)
{
static int f_ct32_e8e9_bswap_be(Filter *f) {
CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_be32, set_le32)
}
// unfilter: e8, e9, e8e9 with bswap be->le
static int u_ct32_e8_bswap_be(Filter *f)
{
static int u_ct32_e8_bswap_be(Filter *f) {
CT32(f, (*b == 0xe8), 0 - a - f->addvalue, get_le32, set_be32)
}
static int u_ct32_e9_bswap_be(Filter *f)
{
static int u_ct32_e9_bswap_be(Filter *f) {
CT32(f, (*b == 0xe9), 0 - a - f->addvalue, get_le32, set_be32)
}
static int u_ct32_e8e9_bswap_be(Filter *f)
{
static int u_ct32_e8e9_bswap_be(Filter *f) {
CT32(f, (*b == 0xe8 || *b == 0xe9), 0 - a - f->addvalue, get_le32, set_be32)
}
// scan: e8, e9, e8e9 with bswap be->le
static int s_ct32_e8_bswap_be(Filter *f)
{
static int s_ct32_e8_bswap_be(Filter *f) {
CT32(f, (*b == 0xe8), a + f->addvalue, get_le32, set_dummy)
}
static int s_ct32_e9_bswap_be(Filter *f)
{
static int s_ct32_e9_bswap_be(Filter *f) {
CT32(f, (*b == 0xe9), a + f->addvalue, get_le32, set_dummy)
}
static int s_ct32_e8e9_bswap_be(Filter *f)
{
static int s_ct32_e8e9_bswap_be(Filter *f) {
CT32(f, (*b == 0xe8 || *b == 0xe9), a + f->addvalue, get_le32, set_dummy)
}
#undef CT32
/*************************************************************************
// 24-bit ARM calltrick ("naive")
**************************************************************************/
#define CT24ARM_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; \
#define CT24ARM_LE(f, cond, addvalue, get, set) \
byte *b = f->buf; \
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_le (((b[3] & 0x0f) == 0x0b))
static int f_ct24arm_le(Filter *f)
{
static int f_ct24arm_le(Filter *f) {
CT24ARM_LE(f, ARMCT_COND_le, a / 4 + f->addvalue, get_le24, set_le24)
}
static int u_ct24arm_le(Filter *f)
{
static int u_ct24arm_le(Filter *f) {
CT24ARM_LE(f, ARMCT_COND_le, 0 - a / 4 - f->addvalue, get_le24, set_le24)
}
static int s_ct24arm_le(Filter *f)
{
static int s_ct24arm_le(Filter *f) {
CT24ARM_LE(f, ARMCT_COND_le, a + f->addvalue, get_le24, set_dummy)
}
#undef CT24ARM_LE
#define CT24ARM_BE(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(1+b, get(1+b) + (addvalue)); \
f->calls++; \
} \
b += 4; \
} while (b < b_end); \
if (f->lastcall) f->lastcall += 4; \
#define CT24ARM_BE(f, cond, addvalue, get, set) \
byte *b = f->buf; \
byte *b_end = b + f->buf_len - 4; \
do { \
if (cond) { \
unsigned a = (unsigned) (b - f->buf); \
f->lastcall = a; \
set(1 + b, get(1 + b) + (addvalue)); \
f->calls++; \
} \
b += 4; \
} while (b < b_end); \
if (f->lastcall) \
f->lastcall += 4; \
return 0;
#define ARMCT_COND_be (((b[0] & 0x0f) == 0x0b))
static int f_ct24arm_be(Filter *f)
{
static int f_ct24arm_be(Filter *f) {
CT24ARM_BE(f, ARMCT_COND_be, a / 4 + f->addvalue, get_be24, set_be24)
}
static int u_ct24arm_be(Filter *f)
{
static int u_ct24arm_be(Filter *f) {
CT24ARM_BE(f, ARMCT_COND_be, 0 - a / 4 - f->addvalue, get_be24, set_be24)
}
static int s_ct24arm_be(Filter *f)
{
static int s_ct24arm_be(Filter *f) {
CT24ARM_BE(f, ARMCT_COND_be, a + f->addvalue, get_be24, set_dummy)
}
@@ -463,40 +354,80 @@ static int s_ct24arm_be(Filter *f)
// 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; \
#if 1 //{ old reliable
#define CT26ARM_LE(f, cond, addvalue, get, set) \
byte *b = f->buf; \
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)
{
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)
{
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)
{
static int s_ct26arm_le(Filter *f) {
CT26ARM_LE(f, ARMCT_COND, a + f->addvalue, get_le26, set_dummy)
}
#else //}{ new enhanced but DIFFERENT; need new filter type!
static int CTarm64(Filter *f, int dir) // dir: 1, 0, -1
{
upx_byte *b = f->buf; // will be incremented
upx_byte *const b_end = b + f->buf_len - 4;
do {
unsigned const a = b - f->buf;
int const d = dir * (f->addvalue + (a >> 2));
unsigned const v = get_le32(f->buf); // the 32-bit instruction
if (0x05 == (0x1f & (v >> 26))) { // b, bl
f->lastcall = a;
if (dir)
set_le26(b, v + d);
f->calls++;
} else if ((0x54 == (v >> 24)) // b.cond
|| (0x1a == ((v >> 25) & 0x3f)) // cb{z,nz}
) {
f->lastcall = a;
if (dir)
set_le19_5(b, (v >> 5) + d);
f->calls++;
} else if (0x1b == ((v >> 25) & 0x3f)) { // tb{z,nz}
f->lastcall = a;
if (dir)
set_le14_5(b, (v >> 5) + d);
f->calls++;
}
b += 4;
} while (b < b_end);
if (f->lastcall)
f->lastcall += 4;
return 0;
}
static int f_CTarm64_le(Filter *f) { return CTarm64(f, 1); }
static int u_CTarm64_le(Filter *f) { return CTarm64(f, -1); }
static int s_CTarm64_le(Filter *f) { return CTarm64(f, 0); }
#endif //}
#undef CT26ARM_LE
#undef ARMCT_COND
+34 -52
View File
@@ -25,20 +25,17 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com>
*/
/*************************************************************************
// filter / scan
**************************************************************************/
static int F(Filter *f)
{
static int F(Filter *f) {
#ifdef U
// filter
upx_byte *b = f->buf;
byte *b = f->buf;
#else
// scan
const upx_byte *b = f->buf;
const byte *b = f->buf;
#endif
const unsigned addvalue = f->addvalue;
const unsigned size = f->buf_len;
@@ -50,25 +47,22 @@ static int F(Filter *f)
// find a 16 MiB large empty address space
{
unsigned char buf[256];
memset(buf,0,256);
memset(buf, 0, 256);
// A call to a destination that is inside the buffer
// will be rewritten and marked with cto8 as first byte.
// So, a call to a destination that is outside the buffer
// must not conflict with the mark.
// Note that unsigned comparison checks both edges of buffer.
for (ic = 0; ic < size - 5; ic++)
{
if (!COND(b,ic))
for (ic = 0; ic < size - 5; ic++) {
if (!COND(b, ic))
continue;
jc = get_le32(b+ic+1)+ic+1;
if (jc < size)
{
jc = get_le32(b + ic + 1) + ic + 1;
if (jc < size) {
if (jc + addvalue >= (1u << 24)) // hi 8 bits won't be cto8
return -1;
}
else
buf[b[ic+1]] |= 1;
} else
buf[b[ic + 1]] |= 1;
}
if (getcto(f, buf) < 0)
@@ -76,35 +70,31 @@ static int F(Filter *f)
}
const unsigned char cto8 = f->cto;
#ifdef U
const unsigned cto = (unsigned)f->cto << 24;
const unsigned cto = (unsigned) f->cto << 24;
#endif
for (ic = 0; ic < size - 5; ic++)
{
if (!COND(b,ic))
for (ic = 0; ic < size - 5; ic++) {
if (!COND(b, ic))
continue;
jc = get_le32(b+ic+1)+ic+1;
jc = get_le32(b + ic + 1) + ic + 1;
// try to detect 'real' calls only
if (jc < size)
{
if (jc < size) {
assert(jc + addvalue < (1u << 24)); // hi 8 bits won't be cto8
#ifdef U
set_be32(b+ic+1,jc+addvalue+cto);
set_be32(b + ic + 1, jc + addvalue + cto);
#endif
if (ic - lastnoncall < 5)
{
if (ic - lastnoncall < 5) {
// check the last 4 bytes before this call
for (kc = 4; kc; kc--)
if (COND(b,ic-kc) && b[ic-kc+1] == cto8)
if (COND(b, ic - kc) && b[ic - kc + 1] == cto8)
break;
if (kc)
{
if (kc) {
#ifdef U
// restore original
set_le32(b+ic+1,jc-ic-1);
set_le32(b + ic + 1, jc - ic - 1);
#endif
if (b[ic+1] == cto8)
return 1; // fail - buffer not restored
if (b[ic + 1] == cto8)
return 1; // fail - buffer not restored
lastnoncall = ic;
noncalls2++;
continue;
@@ -112,11 +102,9 @@ static int F(Filter *f)
}
calls++;
ic += 4;
lastcall = ic+1;
}
else
{
assert(b[ic+1] != cto8); // this should not happen
lastcall = ic + 1;
} else {
assert(b[ic + 1] != cto8); // this should not happen
lastnoncall = ic;
noncalls++;
}
@@ -133,40 +121,34 @@ static int F(Filter *f)
return 0;
}
/*************************************************************************
// unfilter
**************************************************************************/
#ifdef U
static int U(Filter *f)
{
upx_byte *b = f->buf;
static int U(Filter *f) {
byte *b = f->buf;
const unsigned size5 = f->buf_len - 5;
const unsigned addvalue = f->addvalue;
const unsigned cto = (unsigned)f->cto << 24;
const unsigned cto = (unsigned) f->cto << 24;
unsigned ic, jc;
for (ic = 0; ic < size5; ic++)
if (COND(b,ic))
{
jc = get_be32(b+ic+1);
if (b[ic+1] == f->cto)
{
set_le32(b+ic+1,jc-ic-1-addvalue-cto);
if (COND(b, ic)) {
jc = get_be32(b + ic + 1);
if (b[ic + 1] == f->cto) {
set_le32(b + ic + 1, jc - ic - 1 - addvalue - cto);
f->calls++;
ic += 4;
f->lastcall = ic+1;
}
else
f->lastcall = ic + 1;
} else
f->noncalls++;
}
return 0;
}
#endif
#undef F
#undef U
+35 -53
View File
@@ -29,20 +29,17 @@
<jreiser@users.sourceforge.net>
*/
/*************************************************************************
// filter / scan
**************************************************************************/
static int F(Filter *f)
{
static int F(Filter *f) {
#ifdef U
// filter
upx_byte *b = f->buf;
byte *b = f->buf;
#else
// scan
const upx_byte *b = f->buf;
const byte *b = f->buf;
#endif
const unsigned addvalue = f->addvalue;
const unsigned size = f->buf_len;
@@ -54,20 +51,17 @@ static int F(Filter *f)
// find a 16 MiB large empty address space
{
unsigned char buf[256];
memset(buf,0,256);
memset(buf, 0, 256);
for (ic = 0; ic < size - 5; ic++)
{
if (!COND(b,ic,lastcall))
for (ic = 0; ic < size - 5; ic++) {
if (!COND(b, ic, lastcall))
continue;
jc = get_le32(b+ic+1)+ic+1;
if (jc < size)
{
jc = get_le32(b + ic + 1) + ic + 1;
if (jc < size) {
if (jc + addvalue >= (1u << 24)) // hi 8 bits won't be cto8
return -1;
}
else
buf[b[ic+1]] |= 1;
} else
buf[b[ic + 1]] |= 1;
}
if (getcto(f, buf) < 0)
@@ -75,35 +69,31 @@ static int F(Filter *f)
}
const unsigned char cto8 = f->cto;
#ifdef U
const unsigned cto = (unsigned)f->cto << 24;
const unsigned cto = (unsigned) f->cto << 24;
#endif
for (ic = 0; ic < size - 5; ic++)
{
if (!COND(b,ic,lastcall))
for (ic = 0; ic < size - 5; ic++) {
if (!COND(b, ic, lastcall))
continue;
jc = get_le32(b+ic+1)+ic+1;
jc = get_le32(b + ic + 1) + ic + 1;
// try to detect 'real' calls only
if (jc < size)
{
if (jc < size) {
assert(jc + addvalue < (1u << 24)); // hi 8 bits won't be cto8
#ifdef U
set_be32(b+ic+1,jc+addvalue+cto);
set_be32(b + ic + 1, jc + addvalue + cto);
#endif
if (ic - lastnoncall < 5)
{
if (ic - lastnoncall < 5) {
// check the last 4 bytes before this call
for (kc = 4; kc; kc--)
if (COND(b,ic-kc,lastcall) && b[ic-kc+1] == cto8)
if (COND(b, ic - kc, lastcall) && b[ic - kc + 1] == cto8)
break;
if (kc)
{
if (kc) {
#ifdef U
// restore original
set_le32(b+ic+1,jc-ic-1);
set_le32(b + ic + 1, jc - ic - 1);
#endif
if (b[ic+1] == cto8)
return 1; // fail - buffer not restored
if (b[ic + 1] == cto8)
return 1; // fail - buffer not restored
lastnoncall = ic;
noncalls2++;
continue;
@@ -111,11 +101,9 @@ static int F(Filter *f)
}
calls++;
ic += 4;
lastcall = ic+1;
}
else
{
assert(b[ic+1] != cto8); // this should not happen
lastcall = ic + 1;
} else {
assert(b[ic + 1] != cto8); // this should not happen
lastnoncall = ic;
noncalls++;
}
@@ -132,40 +120,34 @@ static int F(Filter *f)
return 0;
}
/*************************************************************************
// unfilter
**************************************************************************/
#ifdef U
static int U(Filter *f)
{
upx_byte *b = f->buf;
static int U(Filter *f) {
byte *b = f->buf;
const unsigned size5 = f->buf_len - 5;
const unsigned addvalue = f->addvalue;
const unsigned cto = (unsigned)f->cto << 24;
// unsigned lastcall = 0; // lastcall is not used in COND macro
const unsigned cto = (unsigned) f->cto << 24;
// unsigned lastcall = 0; // lastcall is not used in COND macro
unsigned ic, jc;
for (ic = 0; ic < size5; ic++)
if (COND(b,ic,lastcall))
{
jc = get_be32(b+ic+1);
if (b[ic+1] == f->cto)
{
set_le32(b+ic+1,jc-ic-1-addvalue-cto);
if (COND(b, ic, lastcall)) {
jc = get_be32(b + ic + 1);
if (b[ic + 1] == f->cto) {
set_le32(b + ic + 1, jc - ic - 1 - addvalue - cto);
f->calls++;
ic += 4;
f->lastcall = ic+1;
}
else
f->lastcall = ic + 1;
} else
f->noncalls++;
}
return 0;
}
#endif
#undef F
#undef U
+119 -161
View File
@@ -29,111 +29,90 @@
<jreiser@users.sourceforge.net>
*/
#if (ACC_CC_MSC && (_MSC_VER >= 1000 && _MSC_VER < 1300))
# pragma warning(disable: 4702) // W4: unreachable code
#pragma warning(disable : 4702) // W4: unreachable code
#endif
/*************************************************************************
// filter / scan
**************************************************************************/
#ifdef U //{
#define NOFILT 0 // no filter
#define FNOMRU 1 // filter, but not using mru
#define MRUFLT 2 // mru filter
#ifdef U //{
#define NOFILT 0 // no filter
#define FNOMRU 1 // filter, but not using mru
#define MRUFLT 2 // mru filter
static unsigned
f80_call(Filter const *f)
{
return (1+ (0x0f & f->id)) % 3;
}
static unsigned f80_call(Filter const *f) { return (1 + (0x0f & f->id)) % 3; }
static unsigned
f80_jmp1(Filter const *f)
{
return ((1+ (0x0f & f->id)) / 3) % 3;
}
static unsigned f80_jmp1(Filter const *f) { return ((1 + (0x0f & f->id)) / 3) % 3; }
static unsigned
f80_jcc2(Filter const *f)
{
return f80_jmp1(f);
}
static unsigned f80_jcc2(Filter const *f) { return f80_jmp1(f); }
#define 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
update_mru(
unsigned const jc, // destination address
int const kh, // mru[kh] is slot where found
unsigned mru[N_MRU], // circular buffer of most recent destinations
int &hand, // mru[hand] is most recent destination
int &tail // mru[tail] is beyond oldest destination ("cold cache" startup)
)
{
static void update_mru(const unsigned jc, // destination address
const int kh, // mru[kh] is slot where found
unsigned mru[N_MRU], // circular buffer of most recent destinations
int &hand, // mru[hand] is most recent destination
int &tail // mru[tail] is beyond oldest destination ("cold cache" startup)
) {
if (0 > --hand) {
hand = N_MRU -1;
hand = N_MRU - 1;
}
unsigned const t = mru[hand]; // entry which will be overwritten by jc
if (0!=t) { // have seen at least N_MRU destinations
const unsigned t = mru[hand]; // entry which will be overwritten by jc
if (0 != t) { // have seen at least N_MRU destinations
mru[kh] = t;
}
else { // "cold cache": keep active region contiguous
} else { // "cold cache": keep active region contiguous
if (0 > --tail) {
tail = N_MRU -1;
tail = N_MRU - 1;
}
unsigned const t2 = mru[tail];
const unsigned t2 = mru[tail];
mru[tail] = 0;
mru[kh] = t2;
}
mru[hand] = jc;
}
#endif //}
#endif //}
static int F(Filter *f)
{
static int F(Filter *f) {
#ifdef U
// filter
upx_byte *const b = f->buf;
byte *const b = f->buf;
#else
// scan
const upx_byte *b = f->buf;
const byte *b = f->buf;
#endif
const unsigned size = f->buf_len;
unsigned ic, jc, kc;
unsigned calls = 0, noncalls = 0, noncalls2 = 0;
unsigned lastnoncall = size, lastcall = 0;
unsigned wtally[3]; memset(wtally, 0, sizeof(wtally));
unsigned wtally[3];
memset(wtally, 0, sizeof(wtally));
#ifdef U //{
unsigned const f_call = f80_call(f);
unsigned const f_jmp1 = f80_jmp1(f);
unsigned const f_jcc2 = f80_jcc2(f);
#ifdef U //{
const unsigned f_call = f80_call(f);
const unsigned f_jmp1 = f80_jmp1(f);
const unsigned f_jcc2 = f80_jcc2(f);
int hand = 0, tail = 0;
unsigned mru[N_MRU];
memset(&mru[0], 0, sizeof(mru));
assert(N_MRU<=256);
f->n_mru = (MRUFLT==f_call || MRUFLT==f_jmp1 || MRUFLT==f_jcc2) ?
N_MRU : 0;
#endif //}
assert(N_MRU <= 256);
f->n_mru = (MRUFLT == f_call || MRUFLT == f_jmp1 || MRUFLT == f_jcc2) ? N_MRU : 0;
#endif //}
// FIXME: We must fit into 8 MiB because we steal one bit.
// find a 16 MiB large empty address space
{
int which;
unsigned char buf[256];
memset(buf,0,256);
memset(buf, 0, 256);
for (ic = 0; ic < size - 5; ic++)
if (CONDF(which,b,ic,lastcall) && get_le32(b+ic+1)+ic+1 >= size)
{
buf[b[ic+1]] |= 1;
if (CONDF(which, b, ic, lastcall) && get_le32(b + ic + 1) + ic + 1 >= size) {
buf[b[ic + 1]] |= 1;
}
UNUSED(which);
@@ -142,37 +121,33 @@ static int F(Filter *f)
}
const unsigned char cto8 = f->cto;
#ifdef U
const unsigned cto = (unsigned)f->cto << 24;
const unsigned cto = (unsigned) f->cto << 24;
#endif
for (ic = 0; ic < size - 5; ic++)
{
for (ic = 0; ic < size - 5; ic++) {
int which;
int f_on = 0;
if (!CONDF(which,b,ic,lastcall))
if (!CONDF(which, b, ic, lastcall))
continue;
++wtally[which];
jc = get_le32(b+ic+1)+ic+1;
jc = get_le32(b + ic + 1) + ic + 1;
// try to detect 'real' calls only
if (jc < size)
{
if (jc < size) {
#ifdef U
if (2==which && NOFILT!=f_jcc2) { // 6-byte Jcc <disp32>
if (2 == which && NOFILT != f_jcc2) { // 6-byte Jcc <disp32>
// Prefix 0x0f is constant, but opcode condition 0x80..0x8f
// varies. Because we store the destination (or its mru index)
// in be32 big endian format, the low-addressed bytes
// will tend to be constant. Swap prefix and opcode
// so that constants are together for better compression.
unsigned char const t =
b[ic-1];
b[ic-1] = b[ic];
b[ic] = t;
unsigned char const t = b[ic - 1];
b[ic - 1] = b[ic];
b[ic] = t;
}
// FIXME [?]: Extend to 8 bytes if "ADD ESP, byte 4*n" follows CALL.
// This will require two related cto's (consecutive, or otherwise).
if ((0==which && MRUFLT==f_call)
|| (1==which && MRUFLT==f_jmp1)
|| (2==which && MRUFLT==f_jcc2) ) {
// FIXME [?]: Extend to 8 bytes if "ADD ESP, byte 4*n" follows CALL.
// This will require two related cto's (consecutive, or otherwise).
if ((0 == which && MRUFLT == f_call) || (1 == which && MRUFLT == f_jmp1) ||
(2 == which && MRUFLT == f_jcc2)) {
f_on = 1;
// Recode the destination: narrower mru indices
// should compress better than wider addresses.
@@ -184,62 +159,55 @@ static int F(Filter *f)
kh -= N_MRU;
}
if (mru[kh] == jc) { // destination was seen recently
set_be32(b+ic+1,((k<<1)|0)+cto);
set_be32(b + ic + 1, ((k << 1) | 0) + cto);
update_mru(jc, kh, mru, hand, tail);
break;
}
}
if (k == N_MRU) { // loop failed; jc is not in mru[]
set_be32(b+ic+1,((jc<<1)|1)+cto);
set_be32(b + ic + 1, ((jc << 1) | 1) + cto);
// Adaptively remember recent destinations.
if (0 > --hand) {
hand = N_MRU -1;
hand = N_MRU - 1;
}
mru[hand] = jc;
}
} else
if ((0==which && NOFILT!=f_call)
|| (1==which && NOFILT!=f_jmp1)
|| (2==which && NOFILT!=f_jcc2) ) {
} else if ((0 == which && NOFILT != f_call) || (1 == which && NOFILT != f_jmp1) ||
(2 == which && NOFILT != f_jcc2)) {
f_on = 1;
set_be32(b+ic+1, jc+cto);
set_be32(b + ic + 1, jc + cto);
}
#endif
if (f_on) {
if (ic - lastnoncall < 5)
{
// check the last 4 bytes before this call
for (kc = 4; kc; kc--)
if (CONDF(which,b,ic-kc,lastcall) && b[ic-kc+1] == cto8)
break;
if (kc)
{
#ifdef U
// restore original
if (2==which) {
// Unswap prefix and opcode for 6-byte Jcc <disp32>
unsigned char const t =
b[ic-1];
b[ic-1] = b[ic];
b[ic] = t;
}
set_le32(b+ic+1,jc-ic-1);
#endif
if (b[ic+1] == cto8)
return 1; // fail - buffer not restored
lastnoncall = ic;
noncalls2++;
continue;
if (ic - lastnoncall < 5) {
// check the last 4 bytes before this call
for (kc = 4; kc; kc--)
if (CONDF(which, b, ic - kc, lastcall) && b[ic - kc + 1] == cto8)
break;
if (kc) {
#ifdef U
// restore original
if (2 == which) {
// Unswap prefix and opcode for 6-byte Jcc <disp32>
unsigned char const t = b[ic - 1];
b[ic - 1] = b[ic];
b[ic] = t;
}
set_le32(b + ic + 1, jc - ic - 1);
#endif
if (b[ic + 1] == cto8)
return 1; // fail - buffer not restored
lastnoncall = ic;
noncalls2++;
continue;
}
calls++;
ic += 4;
lastcall = ic+1;
}
calls++;
ic += 4;
lastcall = ic + 1;
}
}
else
{
assert(b[ic+1] != cto8); // this should not happen
} else {
assert(b[ic + 1] != cto8); // this should not happen
lastnoncall = ic;
noncalls++;
}
@@ -258,82 +226,72 @@ static int F(Filter *f)
return 0;
}
/*************************************************************************
// unfilter
**************************************************************************/
#ifdef U
static int U(Filter *f)
{
static int U(Filter *f) {
unsigned ic, jc;
upx_byte *const b = f->buf;
byte *const b = f->buf;
const unsigned size5 = f->buf_len - 5;
const unsigned cto = (unsigned)f->cto << 24;
const unsigned cto = (unsigned) f->cto << 24;
unsigned lastcall = 0;
int hand = 0, tail = 0;
unsigned const f_call = f80_call(f);
unsigned const f_jmp1 = f80_jmp1(f);
unsigned const f_jcc2 = f80_jcc2(f);
const unsigned f_call = f80_call(f);
const unsigned f_jmp1 = f80_jmp1(f);
const unsigned f_jcc2 = f80_jcc2(f);
unsigned mru[N_MRU];
memset(&mru[0], 0, sizeof(mru));
for (ic = 0; ic < size5; ic++) {
int which;
if (CONDU(which,b,ic,lastcall))
{
if (CONDU(which, b, ic, lastcall)) {
unsigned f_on = 0;
jc = get_be32(b+ic+1) - cto;
if (b[ic+1] == f->cto)
{
if ((0==which && MRUFLT==f_call)
|| (1==which && MRUFLT==f_jmp1)
|| (2==which && MRUFLT==f_jcc2) ) {
jc = get_be32(b + ic + 1) - cto;
if (b[ic + 1] == f->cto) {
if ((0 == which && MRUFLT == f_call) || (1 == which && MRUFLT == f_jmp1) ||
(2 == which && MRUFLT == f_jcc2)) {
f_on = 1;
if (1&jc) { // 1st time at this destination
jc >>= 1;
if (0 > --hand) {
hand = N_MRU -1;
}
mru[hand] = jc;
if (1 & jc) { // 1st time at this destination
jc >>= 1;
if (0 > --hand) {
hand = N_MRU - 1;
}
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;
}
jc = mru[kh];
update_mru(jc, kh, mru, hand, tail);
mru[hand] = jc;
} else { // not 1st time at this destination
jc >>= 1;
if (N_MRU <= jc) {
throwCompressedDataViolation();
}
set_le32(b+ic+1,jc-ic-1);
} else
if ((0==which && NOFILT!=f_call)
|| (1==which && NOFILT!=f_jmp1)
|| (2==which && NOFILT!=f_jcc2) ) {
int kh = jc + hand;
if (N_MRU <= kh) {
kh -= N_MRU;
}
jc = mru[kh];
update_mru(jc, kh, mru, hand, tail);
}
set_le32(b + ic + 1, jc - ic - 1);
} else if ((0 == which && NOFILT != f_call) || (1 == which && NOFILT != f_jmp1) ||
(2 == which && NOFILT != f_jcc2)) {
f_on = 1;
set_le32(b+ic+1,jc-ic-1);
set_le32(b + ic + 1, jc - ic - 1);
}
if (2==which && NOFILT!=f_jcc2) {
if (2 == which && NOFILT != f_jcc2) {
// Unswap prefix and opcode for 6-byte Jcc <disp32>
unsigned char const t =
b[ic-1];
b[ic-1] = b[ic];
b[ic] = t;
unsigned char const t = b[ic - 1];
b[ic - 1] = b[ic];
b[ic] = t;
}
if (f_on) {
f->calls++;
ic += 4;
f->lastcall = lastcall = ic+1;
f->lastcall = lastcall = ic + 1;
}
}
else
} else
f->noncalls++;
}
}
+36 -54
View File
@@ -29,24 +29,21 @@
<jreiser@users.sourceforge.net>
*/
/*************************************************************************
// filter / scan
**************************************************************************/
static int F(Filter *f)
{
static int F(Filter *f) {
#ifdef U
// filter
upx_byte *b = f->buf;
byte *b = f->buf;
#else
// scan
const upx_byte *b = f->buf;
const byte *b = f->buf;
#endif
const unsigned addvalue = f->addvalue;
const unsigned size = f->buf_len;
unsigned const id = f->id;
const unsigned id = f->id;
unsigned ic, jc, kc;
unsigned calls = 0, noncalls = 0, noncalls2 = 0;
@@ -55,20 +52,17 @@ static int F(Filter *f)
// find a 16 MiB large empty address space
{
unsigned char buf[256];
memset(buf,0,256);
memset(buf, 0, 256);
for (ic = 0; ic < size - 5; ic++)
{
if (!COND(b,ic,lastcall,id))
for (ic = 0; ic < size - 5; ic++) {
if (!COND(b, ic, lastcall, id))
continue;
jc = get_le32(b+ic+1)+ic+1;
if (jc < size)
{
jc = get_le32(b + ic + 1) + ic + 1;
if (jc < size) {
if (jc + addvalue >= (1u << 24)) // hi 8 bits won't be cto8
return -1;
}
else
buf[b[ic+1]] |= 1;
} else
buf[b[ic + 1]] |= 1;
}
if (getcto(f, buf) < 0)
@@ -76,35 +70,31 @@ static int F(Filter *f)
}
const unsigned char cto8 = f->cto;
#ifdef U
const unsigned cto = (unsigned)f->cto << 24;
const unsigned cto = (unsigned) f->cto << 24;
#endif
for (ic = 0; ic < size - 5; ic++)
{
if (!COND(b,ic,lastcall,id))
for (ic = 0; ic < size - 5; ic++) {
if (!COND(b, ic, lastcall, id))
continue;
jc = get_le32(b+ic+1)+ic+1;
jc = get_le32(b + ic + 1) + ic + 1;
// try to detect 'real' calls only
if (jc < size)
{
if (jc < size) {
assert(jc + addvalue < (1u << 24)); // hi 8 bits won't be cto8
#ifdef U
set_be32(b+ic+1,jc+addvalue+cto);
set_be32(b + ic + 1, jc + addvalue + cto);
#endif
if (ic - lastnoncall < 5)
{
if (ic - lastnoncall < 5) {
// check the last 4 bytes before this call
for (kc = 4; kc; kc--)
if (COND(b,ic-kc,lastcall,id) && b[ic-kc+1] == cto8)
if (COND(b, ic - kc, lastcall, id) && b[ic - kc + 1] == cto8)
break;
if (kc)
{
if (kc) {
#ifdef U
// restore original
set_le32(b+ic+1,jc-ic-1);
set_le32(b + ic + 1, jc - ic - 1);
#endif
if (b[ic+1] == cto8)
return 1; // fail - buffer not restored
if (b[ic + 1] == cto8)
return 1; // fail - buffer not restored
lastnoncall = ic;
noncalls2++;
continue;
@@ -112,11 +102,9 @@ static int F(Filter *f)
}
calls++;
ic += 4;
lastcall = ic+1;
}
else
{
assert(b[ic+1] != cto8); // this should not happen
lastcall = ic + 1;
} else {
assert(b[ic + 1] != cto8); // this should not happen
lastnoncall = ic;
noncalls++;
}
@@ -133,42 +121,36 @@ static int F(Filter *f)
return 0;
}
/*************************************************************************
// unfilter
**************************************************************************/
#ifdef U
static int U(Filter *f)
{
upx_byte *b = f->buf;
static int U(Filter *f) {
byte *b = f->buf;
const unsigned size5 = f->buf_len - 5;
const unsigned addvalue = f->addvalue;
const unsigned cto = (unsigned)f->cto << 24;
unsigned const id = f->id;
const unsigned cto = (unsigned) f->cto << 24;
const unsigned id = f->id;
unsigned lastcall = 0;
unsigned ic, jc;
for (ic = 0; ic < size5; ic++)
if (COND(b,ic,lastcall,id))
{
jc = get_be32(b+ic+1);
if (b[ic+1] == f->cto)
{
set_le32(b+ic+1,jc-ic-1-addvalue-cto);
if (COND(b, ic, lastcall, id)) {
jc = get_be32(b + ic + 1);
if (b[ic + 1] == f->cto) {
set_le32(b + ic + 1, jc - ic - 1 - addvalue - cto);
f->calls++;
ic += 4;
f->lastcall = lastcall = ic+1;
}
else
f->lastcall = lastcall = ic + 1;
} else
f->noncalls++;
}
return 0;
}
#endif
#undef F
#undef U
+56 -83
View File
@@ -25,145 +25,118 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com>
*/
/*************************************************************************
// 16-bit call-/swaptrick ("naive")
**************************************************************************/
#define CTSW16(f, cond1, cond2, addvalue, get, set) \
upx_byte *b = f->buf; \
upx_byte *b_end = b + f->buf_len - 3; \
do { \
if (cond1) \
{ \
b += 1; \
unsigned a = (unsigned) (b - f->buf); \
f->lastcall = a; \
set(b, get(b) + (addvalue)); \
f->calls++; \
b += 2 - 1; \
} \
else if (cond2) \
{ \
b += 1; \
unsigned a = (unsigned) (b - f->buf); \
f->lastcall = a; \
set(b, get(b)); \
f->calls++; \
b += 2 - 1; \
} \
} while (++b < b_end); \
if (f->lastcall) f->lastcall += 2; \
#define CTSW16(f, cond1, cond2, addvalue, get, set) \
byte *b = f->buf; \
byte *b_end = b + f->buf_len - 3; \
do { \
if (cond1) { \
b += 1; \
unsigned a = (unsigned) (b - f->buf); \
f->lastcall = a; \
set(b, get(b) + (addvalue)); \
f->calls++; \
b += 2 - 1; \
} else if (cond2) { \
b += 1; \
unsigned a = (unsigned) (b - f->buf); \
f->lastcall = a; \
set(b, get(b)); \
f->calls++; \
b += 2 - 1; \
} \
} while (++b < b_end); \
if (f->lastcall) \
f->lastcall += 2; \
return 0;
// filter
static int f_ctsw16_e8_e9(Filter *f)
{
static int f_ctsw16_e8_e9(Filter *f) {
CTSW16(f, (*b == 0xe8), (*b == 0xe9), a + f->addvalue, get_le16, set_be16)
}
static int f_ctsw16_e9_e8(Filter *f)
{
static int f_ctsw16_e9_e8(Filter *f) {
CTSW16(f, (*b == 0xe9), (*b == 0xe8), a + f->addvalue, get_le16, set_be16)
}
// unfilter
static int u_ctsw16_e8_e9(Filter *f)
{
static int u_ctsw16_e8_e9(Filter *f) {
CTSW16(f, (*b == 0xe8), (*b == 0xe9), 0 - a - f->addvalue, get_be16, set_le16)
}
static int u_ctsw16_e9_e8(Filter *f)
{
static int u_ctsw16_e9_e8(Filter *f) {
CTSW16(f, (*b == 0xe9), (*b == 0xe8), 0 - a - f->addvalue, get_be16, set_le16)
}
// scan
static int s_ctsw16_e8_e9(Filter *f)
{
static int s_ctsw16_e8_e9(Filter *f) {
CTSW16(f, (*b == 0xe8), (*b == 0xe9), a + f->addvalue, get_le16, set_dummy)
}
static int s_ctsw16_e9_e8(Filter *f)
{
static int s_ctsw16_e9_e8(Filter *f) {
CTSW16(f, (*b == 0xe9), (*b == 0xe8), a + f->addvalue, get_le16, set_dummy)
}
#undef CTSW16
/*************************************************************************
// 32-bit call-/swaptrick ("naive")
**************************************************************************/
#define CTSW32(f, cond1, cond2, addvalue, get, set) \
upx_byte *b = f->buf; \
upx_byte *b_end = b + f->buf_len - 5; \
do { \
if (cond1) \
{ \
b += 1; \
unsigned a = (unsigned) (b - f->buf); \
f->lastcall = a; \
set(b, get(b) + (addvalue)); \
f->calls++; \
b += 4 - 1; \
} \
else if (cond2) \
{ \
b += 1; \
unsigned a = (unsigned) (b - f->buf); \
f->lastcall = a; \
set(b, get(b)); \
f->calls++; \
b += 4 - 1; \
} \
} while (++b < b_end); \
if (f->lastcall) f->lastcall += 4; \
#define CTSW32(f, cond1, cond2, addvalue, get, set) \
byte *b = f->buf; \
byte *b_end = b + f->buf_len - 5; \
do { \
if (cond1) { \
b += 1; \
unsigned a = (unsigned) (b - f->buf); \
f->lastcall = a; \
set(b, get(b) + (addvalue)); \
f->calls++; \
b += 4 - 1; \
} else if (cond2) { \
b += 1; \
unsigned a = (unsigned) (b - f->buf); \
f->lastcall = a; \
set(b, get(b)); \
f->calls++; \
b += 4 - 1; \
} \
} while (++b < b_end); \
if (f->lastcall) \
f->lastcall += 4; \
return 0;
// filter
static int f_ctsw32_e8_e9(Filter *f)
{
static int f_ctsw32_e8_e9(Filter *f) {
CTSW32(f, (*b == 0xe8), (*b == 0xe9), a + f->addvalue, get_le32, set_be32)
}
static int f_ctsw32_e9_e8(Filter *f)
{
static int f_ctsw32_e9_e8(Filter *f) {
CTSW32(f, (*b == 0xe9), (*b == 0xe8), a + f->addvalue, get_le32, set_be32)
}
// unfilter
static int u_ctsw32_e8_e9(Filter *f)
{
static int u_ctsw32_e8_e9(Filter *f) {
CTSW32(f, (*b == 0xe8), (*b == 0xe9), 0 - a - f->addvalue, get_be32, set_le32)
}
static int u_ctsw32_e9_e8(Filter *f)
{
static int u_ctsw32_e9_e8(Filter *f) {
CTSW32(f, (*b == 0xe9), (*b == 0xe8), 0 - a - f->addvalue, get_be32, set_le32)
}
// scan
static int s_ctsw32_e8_e9(Filter *f)
{
static int s_ctsw32_e8_e9(Filter *f) {
CTSW32(f, (*b == 0xe8), (*b == 0xe9), a + f->addvalue, get_le32, set_dummy)
}
static int s_ctsw32_e9_e8(Filter *f)
{
static int s_ctsw32_e9_e8(Filter *f) {
CTSW32(f, (*b == 0xe9), (*b == 0xe8), a + f->addvalue, get_le32, set_dummy)
}
#undef CTSW32
/* vim:set ts=4 sw=4 et: */
+50 -59
View File
@@ -25,21 +25,14 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com>
*/
#include "../conf.h"
#include "../filter.h"
static unsigned
umin(unsigned const a, unsigned const b)
{
return (a<=b) ? a : b;
}
#define set_dummy(p, v) ((void)0)
#define get_8(p) (*(p))
#define set_8(p, v) (*(p) = (v))
static unsigned umin(const unsigned a, const unsigned b) { return (a <= b) ? a : b; }
#define set_dummy(p, v) ((void) 0)
#define get_8(p) (*(p))
#define set_8(p, v) (*(p) = (v))
/*************************************************************************
// util
@@ -47,7 +40,6 @@ umin(unsigned const a, unsigned const b)
#include "getcto.h"
/*************************************************************************
// simple filters: calltrick / swaptrick / delta / ...
**************************************************************************/
@@ -60,86 +52,80 @@ umin(unsigned const a, unsigned const b)
#include "sub16.h"
#include "sub32.h"
/*************************************************************************
// cto calltrick
**************************************************************************/
#define COND(b,x) (b[x] == 0xe8)
#define F f_cto32_e8_bswap_le
#define U u_cto32_e8_bswap_le
#define COND(b, x) (b[x] == 0xe8)
#define F f_cto32_e8_bswap_le
#define U u_cto32_e8_bswap_le
#include "cto.h"
#define F s_cto32_e8_bswap_le
#define F s_cto32_e8_bswap_le
#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
#define COND(b, x) (b[x] == 0xe9)
#define F f_cto32_e9_bswap_le
#define U u_cto32_e9_bswap_le
#include "cto.h"
#define F s_cto32_e9_bswap_le
#define F s_cto32_e9_bswap_le
#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
#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 "cto.h"
#define F s_cto32_e8e9_bswap_le
#define F s_cto32_e8e9_bswap_le
#include "cto.h"
#undef COND
/*************************************************************************
// cto calltrick with jmp
**************************************************************************/
#define COND(b,x,lastcall) (b[x] == 0xe8 || b[x] == 0xe9)
#define F f_ctoj32_e8e9_bswap_le
#define U u_ctoj32_e8e9_bswap_le
#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 "ctoj.h"
#define F s_ctoj32_e8e9_bswap_le
#define F s_ctoj32_e8e9_bswap_le
#include "ctoj.h"
#undef COND
/*************************************************************************
// cto calltrick with jmp, optional jcc
**************************************************************************/
#define COND1(b,x) (b[x] == 0xe8 || b[x] == 0xe9)
#define COND2(b,x,lc) (lc!=(x) && 0xf==b[(x)-1] && 0x80<=b[x] && b[x]<=0x8f)
#define COND(b,x,lc,id) (COND1(b,x) || ((9<=(0xf&(id))) && COND2(b,x,lc)))
#define F f_ctok32_e8e9_bswap_le
#define U u_ctok32_e8e9_bswap_le
#define COND1(b, x) (b[x] == 0xe8 || b[x] == 0xe9)
#define COND2(b, x, lc) (lc != (x) && 0xf == b[(x) -1] && 0x80 <= b[x] && b[x] <= 0x8f)
#define COND(b, x, lc, id) (COND1(b, x) || ((9 <= (0xf & (id))) && COND2(b, x, lc)))
#define F f_ctok32_e8e9_bswap_le
#define U u_ctok32_e8e9_bswap_le
#include "ctok.h"
#define F s_ctok32_e8e9_bswap_le
#define F s_ctok32_e8e9_bswap_le
#include "ctok.h"
#undef COND
#undef COND2
#undef COND1
/*************************************************************************
// cto calltrick with jmp and jcc and relative renumbering
**************************************************************************/
#define COND_CALL(which,b,x) ((which = 0), b[x] == 0xe8)
#define COND_JMP( which,b,x) ((which = 1), b[x] == 0xe9)
#define COND_JCC( which,b,lastcall,x,y,z) ((which = 2), \
(lastcall!=(x) && 0xf==b[y] && 0x80<=b[z] && b[z]<=0x8f))
#define COND1(which,b,x) (COND_CALL(which,b,x) || COND_JMP(which,b,x))
#define COND2(which,b,lastcall,x,y,z) COND_JCC(which,b,lastcall,x,y,z)
#define COND_CALL(which, b, x) ((which = 0), b[x] == 0xe8)
#define COND_JMP(which, b, x) ((which = 1), b[x] == 0xe9)
#define COND_JCC(which, b, lastcall, x, y, z) \
((which = 2), (lastcall != (x) && 0xf == b[y] && 0x80 <= b[z] && b[z] <= 0x8f))
#define COND1(which, b, x) (COND_CALL(which, b, x) || COND_JMP(which, b, x))
#define COND2(which, b, lastcall, x, y, z) COND_JCC(which, b, lastcall, x, y, z)
#define CONDF(which,b,x,lastcall) \
(COND1(which,b,x) || COND2(which,b,lastcall,x,(x)-1, x ))
#define CONDU(which,b,x,lastcall) \
(COND1(which,b,x) || COND2(which,b,lastcall,x, x ,(x)-1))
#define CONDF(which, b, x, lastcall) (COND1(which, b, x) || COND2(which, b, lastcall, x, (x) -1, x))
#define CONDU(which, b, x, lastcall) (COND1(which, b, x) || COND2(which, b, lastcall, x, x, (x) -1))
#define F f_ctojr32_e8e9_bswap_le
#define U u_ctojr32_e8e9_bswap_le
#define F f_ctojr32_e8e9_bswap_le
#define U u_ctojr32_e8e9_bswap_le
#include "ctojr.h"
#define F s_ctojr32_e8e9_bswap_le
#define F s_ctojr32_e8e9_bswap_le
#include "ctojr.h"
#undef CONDU
@@ -150,25 +136,24 @@ umin(unsigned const a, unsigned const b)
#undef COND_JMP
#undef COND_CALL
/*************************************************************************
// PowerPC branch [incl. call] trick
**************************************************************************/
#define COND(b,x) (18==(get_be32(b+x)>>26))
#define F f_ppcbxx
#define U u_ppcbxx
#define COND(b, x) (18 == (get_be32(b + x) >> 26))
#define F f_ppcbxx
#define U u_ppcbxx
#include "ppcbxx.h"
#define F s_ppcbxx
#define F s_ppcbxx
#include "ppcbxx.h"
#undef COND
/*************************************************************************
// database for use in class Filter
**************************************************************************/
const FilterImpl::FilterEntry FilterImpl::filters[] = {
// clang-format off
/*static*/ const FilterImpl::FilterEntry FilterImpl::filters[] = {
// no filter
{ 0x00, 0, 0, nullptr, nullptr, nullptr },
@@ -228,8 +213,13 @@ const FilterImpl::FilterEntry FilterImpl::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 },
#if 1 //{ old reliable
// 26-bit calltrick for arm64
{ 0x52, 8, 0x03ffffff, f_ct26arm_le, u_ct26arm_le, s_ct26arm_le },
#else //}{ new enhanced, but needs new filter id
// 26-bit calltrick for arm64; also 19-bit and 14-bit
{ 0x52, 8, 0x03ffffff, f_CTarm64_le, u_CTarm64_le, s_CTarm64_le },
#endif //}
// 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 },
@@ -260,7 +250,8 @@ const FilterImpl::FilterEntry FilterImpl::filters[] = {
// PowerPC branch+call trick
{ 0xd0, 8, 0, f_ppcbxx, u_ppcbxx, s_ppcbxx },
};
// clang-format on
const int FilterImpl::n_filters = TABLESIZE(filters);
/*static*/ const int FilterImpl::n_filters = TABLESIZE(filters);
/* vim:set ts=4 sw=4 et: */
+6 -12
View File
@@ -25,22 +25,16 @@
<markus@oberhumer.com> <ezerotven+github@gmail.com>
*/
/*************************************************************************
//
**************************************************************************/
static int getcto(Filter *f, const unsigned char *buf, const int n=256)
{
static int getcto(Filter *f, const byte *buf, const int n = 256) {
int ic = n;
if (f->preferred_ctos)
{
for (const int *pc = f->preferred_ctos; *pc >= 0; pc++)
{
if (*pc < n && buf[*pc] == 0)
{
if (f->preferred_ctos) {
for (const int *pc = f->preferred_ctos; *pc >= 0; pc++) {
if (*pc < n && buf[*pc] == 0) {
ic = *pc;
break;
}
@@ -60,10 +54,10 @@ static int getcto(Filter *f, const unsigned char *buf, const int n=256)
break;
if (ic >= n)
//throwCantPack("call trick problem");
// throwCantPack("call trick problem");
return -1;
f->cto = (unsigned char) ic;
f->cto = (byte) ic;
return ic;
}
+46 -50
View File
@@ -29,26 +29,23 @@
<jreiser@users.sourceforge.net>
*/
/*************************************************************************
// filter / scan
**************************************************************************/
#define W_CTO 4 /* width of cto; must match stub/ppc_bxx.S */
#define W_CTO 4 /* width of cto; must match stub/ppc_bxx.S */
static int F(Filter *f)
{
static int F(Filter *f) {
#ifdef U
// filter
upx_byte *b = f->buf;
byte *b = f->buf;
const unsigned addvalue = f->addvalue;
#else
// scan
const upx_byte *b = f->buf;
const byte *b = f->buf;
#endif
const unsigned size = umin(f->buf_len, 0u - (~0u<<(32 - (6+ W_CTO))));
const unsigned size4 = size -4;
const unsigned size = umin(f->buf_len, 0u - (~0u << (32 - (6 + W_CTO))));
const unsigned size4 = size - 4;
unsigned ic;
unsigned calls = 0, noncalls = 0;
@@ -58,18 +55,19 @@ static int F(Filter *f)
{
unsigned char buf[256];
unsigned short wbuf[256];
const size_t WW = (size_t)0 - ((~(size_t)0) << W_CTO); // ???
const size_t WW = (size_t) 0 - ((~(size_t) 0) << W_CTO); // ???
memset(wbuf, 0, sizeof(wbuf));
memset(buf , 0, WW);
memset(buf, 0, WW);
memset(buf + WW, 1, 256 - WW);
for (ic = 0; ic<=size4; ic+=4) if (COND(b,ic)) {
unsigned const off = (int)(get_be32(b+ic)<<6) >>6;
if (size <= (off & (~0u<<2))+ic) {
buf[(~(~0u<<W_CTO)) & (off>>(26 - W_CTO))] |= 1;
++wbuf[0xff&(off>>18)];
for (ic = 0; ic <= size4; ic += 4)
if (COND(b, ic)) {
unsigned const off = (int) (get_be32(b + ic) << 6) >> 6;
if (size <= (off & (~0u << 2)) + ic) {
buf[(~(~0u << W_CTO)) & (off >> (26 - W_CTO))] |= 1;
++wbuf[0xff & (off >> 18)];
}
}
}
if (getcto(f, buf) < 0) {
#if (W_CTO != 0)
@@ -81,29 +79,30 @@ static int F(Filter *f)
}
const unsigned char cto8 = f->cto;
#ifdef U
const unsigned cto = (unsigned)f->cto << (24+2 - W_CTO);
const unsigned cto = (unsigned) f->cto << (24 + 2 - W_CTO);
#endif
for (ic = 0; ic<=size4; ic+=4) if (COND(b,ic)) {
unsigned const word = get_be32(b+ic);
unsigned const off = (int)(word<<6) >>6;
unsigned const jc = (off & (~0u<<2))+ic;
// try to detect 'real' calls only
if (jc < size) {
for (ic = 0; ic <= size4; ic += 4)
if (COND(b, ic)) {
unsigned const word = get_be32(b + ic);
unsigned const off = (int) (word << 6) >> 6;
unsigned const jc = (off & (~0u << 2)) + ic;
// try to detect 'real' calls only
if (jc < size) {
#ifdef U
set_be32(b+ic,(0xfc000003&word) | (jc+addvalue+cto));
set_be32(b + ic, (0xfc000003 & word) | (jc + addvalue + cto));
#endif
calls++;
lastcall = ic;
}
else {
calls++;
lastcall = ic;
} else {
#if (W_CTO != 0)
assert((~(~0u<<W_CTO) & (word>>(24+2 - W_CTO))) != (unsigned) cto8); // this should not happen
assert((~(~0u << W_CTO) & (word >> (24 + 2 - W_CTO))) !=
(unsigned) cto8); // this should not happen
#endif
lastnoncall = ic;
noncalls++;
lastnoncall = ic;
noncalls++;
}
}
}
f->calls = calls;
f->noncalls = noncalls;
@@ -117,37 +116,34 @@ static int F(Filter *f)
return 0;
}
/*************************************************************************
// unfilter
**************************************************************************/
#ifdef U
static int U(Filter *f)
{
upx_byte *b = f->buf;
const unsigned size4 = umin(f->buf_len - 4, 0u - (~0u<<(32 - (6+ W_CTO))));
static int U(Filter *f) {
byte *b = f->buf;
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))) == (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++;
f->lastcall = 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))) == (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++;
f->lastcall = ic;
} else {
f->noncalls++;
}
}
else {
f->noncalls++;
}
}
return 0;
}
#endif
#undef F
#undef U

Some files were not shown because too many files have changed in this diff Show More