diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4568928c..614ecd3b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,8 +12,8 @@ env: CMAKE_REQUIRED_QUIET: OFF DEBIAN_FRONTEND: noninteractive UPX_CMAKE_BUILD_FLAGS: --verbose - # 2023-09-30 - ZIG_DIST_VERSION: 0.12.0-dev.668+c07d6e4c1 + # 2023-10-02 + ZIG_DIST_VERSION: 0.12.0-dev.706+62a0fbdae jobs: job-rebuild-and-verify-stubs: diff --git a/.github/workflows/weekly-ci-cc-alpine-linux.yml b/.github/workflows/weekly-ci-cc-alpine-linux.yml index 87add69e..1ad88efa 100644 --- a/.github/workflows/weekly-ci-cc-alpine-linux.yml +++ b/.github/workflows/weekly-ci-cc-alpine-linux.yml @@ -17,6 +17,7 @@ on: env: CMAKE_REQUIRED_QUIET: OFF DEBIAN_FRONTEND: noninteractive + UPX_CMAKE_CONFIG_FLAGS: -DCMAKE_VERBOSE_MAKEFILE=ON UPX_TESTSUITE_LEVEL: 4 jobs: @@ -41,7 +42,6 @@ jobs: name: ${{ format('container {0}', matrix.container) }} runs-on: ubuntu-latest container: ${{ matrix.container }} - env: { UPX_CMAKE_CONFIG_FLAGS: '-DCMAKE_VERBOSE_MAKEFILE=ON' } steps: - name: ${{ format('Install packages {0}', matrix.container) }} run: | diff --git a/.github/workflows/weekly-ci-cc-alpine-mingw.yml b/.github/workflows/weekly-ci-cc-alpine-mingw.yml index c5d8e9f3..25bea8d7 100644 --- a/.github/workflows/weekly-ci-cc-alpine-mingw.yml +++ b/.github/workflows/weekly-ci-cc-alpine-mingw.yml @@ -8,6 +8,7 @@ on: env: CMAKE_REQUIRED_QUIET: OFF DEBIAN_FRONTEND: noninteractive + UPX_CMAKE_CONFIG_FLAGS: -DCMAKE_VERBOSE_MAKEFILE=ON jobs: job-alpine-mingw: # uses cmake + make @@ -28,7 +29,6 @@ jobs: name: ${{ format('container {0}', matrix.container) }} runs-on: ubuntu-latest container: ${{ matrix.container }} - env: { UPX_CMAKE_CONFIG_FLAGS: '-DCMAKE_VERBOSE_MAKEFILE=ON' } steps: - name: ${{ format('Install packages {0}', matrix.container) }} run: | @@ -54,11 +54,11 @@ jobs: - name: 'Build cmake extra/cross-windows-mingw64/debug' # on Alpine 3.11 and 3.12 CMake does not find AR; Alpine >= 3.13 (with CMake 3.18) works ########run: 'make build/extra/cross-windows-mingw64/debug' - run: 'make build/extra/cross-windows-mingw64/debug UPX_CMAKE_CONFIG_FLAGS="$UPX_CMAKE_CONFIG_FLAGS -DCMAKE_AR=/usr/bin/x86_64-w64-mingw32-ar"' + run: 'make build/extra/cross-windows-mingw64/debug -DCMAKE_AR=/usr/bin/x86_64-w64-mingw32-ar' - name: 'Build cmake extra/cross-windows-mingw64/release' # on Alpine 3.11 and 3.12 CMake does not find AR ########run: 'make build/extra/cross-windows-mingw64/release' - run: 'make build/extra/cross-windows-mingw64/release UPX_CMAKE_CONFIG_FLAGS="$UPX_CMAKE_CONFIG_FLAGS -DCMAKE_AR=/usr/bin/x86_64-w64-mingw32-ar"' + run: 'make build/extra/cross-windows-mingw64/release -DCMAKE_AR=/usr/bin/x86_64-w64-mingw32-ar' - name: 'Make artifact' shell: bash run: | diff --git a/.github/workflows/weekly-ci-cc-zigcc.yml b/.github/workflows/weekly-ci-cc-zigcc.yml index f3188027..0039af93 100644 --- a/.github/workflows/weekly-ci-cc-zigcc.yml +++ b/.github/workflows/weekly-ci-cc-zigcc.yml @@ -10,8 +10,8 @@ on: env: CMAKE_REQUIRED_QUIET: OFF DEBIAN_FRONTEND: noninteractive - # 2023-09-30 - ZIG_DIST_VERSION: 0.12.0-dev.668+c07d6e4c1 + # 2023-10-02 + ZIG_DIST_VERSION: 0.12.0-dev.706+62a0fbdae jobs: job-linux-zigcc: # uses cmake + make diff --git a/.gitignore b/.gitignore index 9bd5a9cb..760afb72 100644 --- a/.gitignore +++ b/.gitignore @@ -6,10 +6,10 @@ /maint* /vendor* -GNUmakefile -MMakefile +GNUmakefile* +MMakefile* Makevars.local* -compile_flags.txt +compile_flags*.txt Tmp* tmp* diff --git a/CMakeLists.txt b/CMakeLists.txt index 4adb26d9..be1dc58a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -292,7 +292,7 @@ endfunction() # targets #*********************************************************************** -# internal settings +# 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 diff --git a/Makefile b/Makefile index 8b9c8d3d..a85145e6 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,6 @@ # make -j # and run build CMAKE = cmake - UPX_CMAKE_BUILD_FLAGS += --parallel ifneq ($(VERBOSE),) #UPX_CMAKE_BUILD_FLAGS += --verbose # requires CMake >= 3.14 @@ -41,263 +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 - .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 +build/%/all: $$(dir $$@)debug $$(dir $$@)release ; + # -# END of Makefile; extra stuff follows +# END of Makefile # -#*********************************************************************** -# 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) -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/%: SCAN_BUILD = scan-build -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 +# extra pre-defined build configurations and some utility; optional +include ./misc/make/Makefile-extra.mk +# developer convenience +ifeq ($(shell uname),Linux) # 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 - -#*********************************************************************** -# 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 - -#*********************************************************************** -# 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'))) diff --git a/misc/make/Makefile-extra.mk b/misc/make/Makefile-extra.mk new file mode 100644 index 00000000..42e6da29 --- /dev/null +++ b/misc/make/Makefile-extra.mk @@ -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'))) diff --git a/misc/scripts/check_whitespace.sh b/misc/scripts/check_whitespace.sh index 91f84269..83b71fb5 100755 --- a/misc/scripts/check_whitespace.sh +++ b/misc/scripts/check_whitespace.sh @@ -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 diff --git a/misc/scripts/check_whitespace_git.sh b/misc/scripts/check_whitespace_git.sh index 7ab20e93..8401f2ab 100755 --- a/misc/scripts/check_whitespace_git.sh +++ b/misc/scripts/check_whitespace_git.sh @@ -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 diff --git a/misc/testsuite/test_symlinks.sh b/misc/testsuite/test_symlinks.sh index f3ec2746..6fa1efa9 100755 --- a/misc/testsuite/test_symlinks.sh +++ b/misc/testsuite/test_symlinks.sh @@ -113,7 +113,7 @@ create_files() { local d for d in z_dir_1 z_dir_2 z_dir_3 z_dir_4; do if [[ -d $d ]]; then - chmod -R +w "./$d" + chmod -R +rwx "./$d" rm -rf "./$d" fi done diff --git a/src/Makefile b/src/Makefile index 6537f7f8..4f6b4e60 100644 --- a/src/Makefile +++ b/src/Makefile @@ -7,12 +7,8 @@ # instead. And see the top-level Makefile for some pre-defined CMake # build configurations. -MAKEFLAGS += -r -export SHELL = /bin/sh - 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)/.. @@ -98,8 +94,7 @@ endif # "make check-whitespace" # -CHECK_WHITESPACE = -ifeq ($(shell uname),Linux) +ifeq ($(shell uname),Linux) # 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) diff --git a/src/check/dt_cxxlib.cpp b/src/check/dt_cxxlib.cpp index 2c7f60ed..6781612a 100644 --- a/src/check/dt_cxxlib.cpp +++ b/src/check/dt_cxxlib.cpp @@ -95,11 +95,14 @@ TEST_CASE("noncopyable") { 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); } /************************************************************************* diff --git a/src/conf.h b/src/conf.h index a4748e22..0257bf24 100644 --- a/src/conf.h +++ b/src/conf.h @@ -757,6 +757,7 @@ extern const char gitrev[]; 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); diff --git a/src/console/s_win32.cpp b/src/console/s_win32.cpp index 5119d5f1..63efe919 100644 --- a/src/console/s_win32.cpp +++ b/src/console/s_win32.cpp @@ -33,23 +33,7 @@ // direct screen access **************************************************************************/ -#if !defined(WIN32_LEAN_AND_MEAN) -#define WIN32_LEAN_AND_MEAN 1 -#endif -#if (defined(_MSC_VER) && (_MSC_VER >= 1000 && _MSC_VER < 1200)) && !defined(__clang__) -/* avoid -W4 warnings in */ -#pragma warning(disable : 4032) -/* avoid -W4 warnings in */ -#pragma warning(disable : 4201 4214 4514) -#endif -#if defined(_MSC_VER) && !defined(__clang__) -/* avoid warnings in some versions of */ -#pragma warning(disable : 5105) -#endif -#if defined(__RSXNT__) -#define timeval win32_timeval /* struct timeval already in */ -#endif -#include +#include "../util/windows_lean.h" #if (HAVE_CONIO_H) #include #endif diff --git a/src/console/screen.h b/src/console/screen.h index 2d5b7e1f..9134e542 100644 --- a/src/console/screen.h +++ b/src/console/screen.h @@ -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: */ diff --git a/src/help.cpp b/src/help.cpp index 89029ad3..1d98f90e 100644 --- a/src/help.cpp +++ b/src/help.cpp @@ -435,4 +435,91 @@ void show_version(bool one_line) { // clang-format on } +/************************************************************************* +// sysinfo +// undocumented and subject to change +**************************************************************************/ + +void show_sysinfo(const char *options_var) { + FILE *f = con_term; + + show_header(); + + if (opt->verbose >= 1) { + con_fprintf(f, "UPX version: "); + fflush(f); + show_version(true); + } + fflush(stdout); + + // Compilation Flags + if (opt->verbose >= 2) { + size_t cf_count = 0; + auto cf_print = [f, &cf_count](const char *name, const char *fmt, upx_int64_t v) noexcept { + if (cf_count++ == 0) + con_fprintf(f, "\nCompilation flags:\n"); + con_fprintf(f, " %s = ", name); + con_fprintf(f, fmt, v); + con_fprintf(f, "\n"); + }; + // OS and libc +#if defined(WINVER) + cf_print("WINVER", "0x%04llx", WINVER + 0); +#endif +#if defined(_WIN32_WINNT) + cf_print("_WIN32_WINNT", "0x%04llx", _WIN32_WINNT + 0); +#endif +#if defined(__MSVCRT_VERSION__) + cf_print("__MSVCRT_VERSION__", "0x%04llx", __MSVCRT_VERSION__ + 0); +#endif +#if defined(_USE_MINGW_ANSI_STDIO) + cf_print("_USE_MINGW_ANSI_STDIO", "%lld", _USE_MINGW_ANSI_STDIO + 0); +#endif +#if defined(__USE_MINGW_ANSI_STDIO) + cf_print("__USE_MINGW_ANSI_STDIO", "%lld", __USE_MINGW_ANSI_STDIO + 0); +#endif +#if defined(__GLIBC__) + cf_print("__GLIBC__", "%lld", __GLIBC__ + 0); +#endif +#if defined(__GLIBC_MINOR__) + cf_print("__GLIBC_MINOR__", "%lld", __GLIBC_MINOR__ + 0); +#endif + // compiler +#if defined(_MSC_VER) && defined(_MSC_FULL_VER) + cf_print("_MSC_VER", "%lld", _MSC_VER + 0); + cf_print("_MSC_FULL_VER", "%lld", _MSC_FULL_VER + 0); +#endif + UNUSED(cf_count); + UNUSED(cf_print); + } + + // run-time +#if defined(HAVE_LOCALTIME) && defined(HAVE_GMTIME) + { + auto tm2str = [](char *s, size_t size, const struct tm *tmp) noexcept { + snprintf(s, size, "%04d-%02d-%02d %02d:%02d:%02d", (int) tmp->tm_year + 1900, + (int) tmp->tm_mon + 1, (int) tmp->tm_mday, (int) tmp->tm_hour, + (int) tmp->tm_min, (int) tmp->tm_sec); + }; + + char s[40]; + const time_t t = time(nullptr); + tm2str(s, sizeof(s), localtime(&t)); + con_fprintf(f, "\n"); + con_fprintf(f, "Local time is: %s\n", s); + tm2str(s, sizeof(s), gmtime(&t)); + con_fprintf(f, "UTC time is: %s\n", s); + } +#endif + + if (options_var && options_var[0]) { + const char *e = getenv(options_var); + con_fprintf(f, "\n"); + if (e && e[0]) + con_fprintf(f, "Contents of environment variable %s: '%s'\n\n", options_var, e); + else + con_fprintf(f, "Environment variable '%s' is not set.\n\n", options_var); + } +} + /* vim:set ts=4 sw=4 et: */ diff --git a/src/main.cpp b/src/main.cpp index 042b435d..89ceaa23 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -374,6 +374,9 @@ static int do_option(int optc, const char *arg) { case 909: set_cmd(CMD_FILEINFO); break; + case 910: + set_cmd(CMD_SYSINFO); + break; case 'h': case 'H': case '?': @@ -807,6 +810,8 @@ int main_get_options(int argc, char **argv) { {"help", 0, N, 'h' + 256}, // give help {"license", 0, N, 'L'}, // display software license {"list", 0, N, 'l'}, // list compressed exe + {"sysinfo", 0x90, N, 910}, // display system info // undocumented and subject to change + {"sys-info", 0x90, N, 910}, // display system info // undocumented and subject to change {"test", 0, N, 't'}, // test compressed file integrity {"uncompress", 0, N, 'd'}, // decompress {"version", 0, N, 'V' + 256}, // display version number @@ -1250,14 +1255,18 @@ int upx_main(int argc, char *argv[]) may_throw { break; case CMD_FILEINFO: break; - case CMD_LICENSE: - show_license(); + case CMD_SYSINFO: + show_sysinfo(OPTIONS_VAR); e_exit(EXIT_OK); break; case CMD_HELP: show_help(1); e_exit(EXIT_OK); break; + case CMD_LICENSE: + show_license(); + e_exit(EXIT_OK); + break; case CMD_VERSION: show_version(); e_exit(EXIT_OK); diff --git a/src/options.h b/src/options.h index ddd18374..83ebd725 100644 --- a/src/options.h +++ b/src/options.h @@ -47,6 +47,7 @@ enum { CMD_TEST, CMD_LIST, CMD_FILEINFO, + CMD_SYSINFO, CMD_HELP, CMD_LICENSE, CMD_VERSION, diff --git a/src/p_djgpp2.h b/src/p_djgpp2.h index 5aaf98bf..48a6e8de 100644 --- a/src/p_djgpp2.h +++ b/src/p_djgpp2.h @@ -26,8 +26,6 @@ */ #pragma once -#ifndef UPX_P_DJGPP2_H__ -#define UPX_P_DJGPP2_H__ 1 /************************************************************************* // djgpp2/coff @@ -104,6 +102,4 @@ protected: void stripDebug(); }; -#endif /* already included */ - /* vim:set ts=4 sw=4 et: */ diff --git a/src/p_lx_exc.h b/src/p_lx_exc.h index 484801c8..d4e792da 100644 --- a/src/p_lx_exc.h +++ b/src/p_lx_exc.h @@ -29,6 +29,7 @@ */ +#pragma once #ifndef __UPX_P_LX_EXC_H #define __UPX_P_LX_EXC_H 1 diff --git a/src/p_lx_interp.h b/src/p_lx_interp.h index 4c464fee..a2762e48 100644 --- a/src/p_lx_interp.h +++ b/src/p_lx_interp.h @@ -30,6 +30,7 @@ */ +#pragma once #ifndef __UPX_P_LX_INTERP_H //{ #define __UPX_P_LX_INTERP_H 1 diff --git a/src/p_lx_sh.h b/src/p_lx_sh.h index 541ae8e5..dd385e05 100644 --- a/src/p_lx_sh.h +++ b/src/p_lx_sh.h @@ -30,6 +30,7 @@ */ +#pragma once #ifndef __UPX_P_LX_SH_H //{ #define __UPX_P_LX_SH_H 1 diff --git a/src/packer.cpp b/src/packer.cpp index ab0fddf6..2e058f3c 100644 --- a/src/packer.cpp +++ b/src/packer.cpp @@ -185,7 +185,7 @@ bool Packer::compress(SPAN_P(byte) i_ptr, unsigned i_len, SPAN_P(byte) o_ptr, opt->crp.crp_ucl.max_match < cconf.conf_ucl.max_match) cconf.conf_ucl.max_match = opt->crp.crp_ucl.max_match; #if (WITH_NRV) - if (ph.level >= 7 || (ph.level >= 4 && ph.u_len >= 512 * 1024)) + if ((ph.level >= 7 || (ph.level >= 4 && ph.u_len >= 512 * 1024)) && !opt->prefer_ucl) step = 0; #endif } diff --git a/src/stub/Makefile b/src/stub/Makefile index 9c581e94..8a6a2645 100644 --- a/src/stub/Makefile +++ b/src/stub/Makefile @@ -1,17 +1,15 @@ # -# UPX stub Makefile - needs GNU make 3.81 or better -# -# Preferred: see misc/podman/rebuild-stubs how to use Podman/Docker. -# Otherwise you will need a number of special build tools like various -# cross-assemblers and cross-compilers - see README.SRC. -# -# Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer +# UPX stub Makefile - needs GNU make +# Copyright (C) Markus Franz Xaver Johannes Oberhumer # +# NOTE: see misc/podman/rebuild-stubs/20-image-run-shell.sh +# how to rebuild the UPX stubs + MAKEFLAGS += -rR -.SUFFIXES: -.SECONDEXPANSION: .NOTPARALLEL: +.SECONDEXPANSION: +.SUFFIXES: export LC_ALL = C export SHELL = /bin/sh @@ -22,8 +20,7 @@ space := $(empty) $(empty) tab := $(empty) $(empty) ifndef srcdir -srcdir := $(dir $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))) -srcdir := $(shell echo '$(srcdir)' | sed 's,/*$$,,') +srcdir := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) endif ifndef top_srcdir top_srcdir := $(srcdir)/../.. diff --git a/src/util/util.cpp b/src/util/util.cpp index 6ad19007..2d324992 100644 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -280,6 +280,7 @@ void upx_memswap(void *a, void *b, size_t n) { static void memswap_no_overlap(byte *a, byte *b, size_t n) { #if defined(__clang__) && __clang_major__ < 15 // work around a clang < 15 ICE (Internal Compiler Error) + // @COMPILER_BUG @CLANG_BUG upx_memswap(a, b, n); #else // clang bug upx_alignas_max byte tmp_buf[16]; @@ -763,7 +764,7 @@ int fn_strcmp(const char *n1, const char *n2) { } /************************************************************************* -// misc. +// misc **************************************************************************/ bool set_method_name(char *buf, size_t size, int method, int level) { diff --git a/src/util/windows_lean.h b/src/util/windows_lean.h new file mode 100644 index 00000000..f73f367c --- /dev/null +++ b/src/util/windows_lean.h @@ -0,0 +1,48 @@ +/* windows_lean.h -- include wrapper + + 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 + + */ + +#pragma once + +#if !defined(WIN32_LEAN_AND_MEAN) +#define WIN32_LEAN_AND_MEAN 1 +#endif + +#if (defined(_MSC_VER) && (_MSC_VER >= 1000 && _MSC_VER < 1200)) && !defined(__clang__) +/* avoid -W4 warnings in */ +#pragma warning(disable : 4032) +/* avoid -W4 warnings in */ +#pragma warning(disable : 4201 4214 4514) +#endif +#if defined(_MSC_VER) && !defined(__clang__) +/* avoid warnings in some versions of */ +#pragma warning(disable : 5105) +#endif + +#if defined(__RSXNT__) && !defined(timeval) +#define timeval win32_timeval /* struct timeval already in */ +#endif + +#include diff --git a/src/util/xspan_impl.h b/src/util/xspan_impl.h index b0c6df81..3dd60c76 100644 --- a/src/util/xspan_impl.h +++ b/src/util/xspan_impl.h @@ -28,6 +28,7 @@ #if WITH_XSPAN +// namespace #if 1 #define XSPAN_NAMESPACE_NAME XSpan #define XSPAN_NAMESPACE_BEGIN namespace XSPAN_NAMESPACE_NAME { @@ -51,12 +52,12 @@ noinline void xspan_fail_range_range(void) may_throw; void xspan_check_range(const void *ptr, const void *base, ptrdiff_t size_in_bytes) may_throw; // help constructor to distinguish between number of elements and bytes -struct XSpanCount { - explicit forceinline XSpanCount(size_t n) noexcept : count(n) {} +struct XSpanCount final { + explicit forceinline constexpr XSpanCount(size_t n) noexcept : count(n) {} size_t count; // public }; -struct XSpanSizeInBytes { - explicit forceinline XSpanSizeInBytes(size_t bytes) noexcept : size_in_bytes(bytes) {} +struct XSpanSizeInBytes final { + explicit forceinline constexpr XSpanSizeInBytes(size_t bytes) noexcept : size_in_bytes(bytes) {} size_t size_in_bytes; // public }; @@ -117,8 +118,8 @@ struct XSpan_is_convertible : public std::is_convertible {}; #else // manual implementation -namespace detail { -// helper for "void" +namespace XSpan_detail { +// XSpan_void_to_T - helper for "void" template struct XSpan_void_to_T { typedef U type; @@ -131,19 +132,18 @@ template struct XSpan_void_to_T { typedef T type; }; - +// XSpan_ptr_is_convertible template struct XSpan_ptr_is_convertible : public std::false_type {}; template struct XSpan_ptr_is_convertible : public std::true_type {}; template struct XSpan_ptr_is_convertible : public std::true_type {}; -} // namespace detail +} // namespace XSpan_detail template -struct XSpan_is_convertible - : public detail::XSpan_ptr_is_convertible::type> {}; +struct XSpan_is_convertible : public XSpan_detail::XSpan_ptr_is_convertible< + From, typename XSpan_detail::XSpan_void_to_T::type> {}; #endif #if DEBUG @@ -193,15 +193,38 @@ template struct Ptr; // XSpanInternalDummyArg: some type that is hard to match by accident -class XSpanInternalDummyArgFake; // not implemented on purpose +// (this should result in efficient code and fully get optimized away) #if 0 +// too simple, can be matched by nullptr +class XSpanInternalDummyArgFake; // not implemented on purpose typedef XSpanInternalDummyArgFake *XSpanInternalDummyArg; #define XSpanInternalDummyArgInit nullptr -#else -struct XSpanInternalDummyArg { - explicit forceinline XSpanInternalDummyArg(int, XSpanInternalDummyArgFake *) noexcept {} +#elif 1 +// use an enum +struct XSpanInternalDummyArg final { + enum DummyEnum {}; + explicit forceinline constexpr XSpanInternalDummyArg(DummyEnum &&) noexcept {} }; -#define XSpanInternalDummyArgInit (XSPAN_NS(XSpanInternalDummyArg)(0, nullptr)) +#define XSpanInternalDummyArgInit \ + (XSPAN_NS(XSpanInternalDummyArg)(XSPAN_NS(XSpanInternalDummyArg)::DummyEnum{})) +#else +// use a class with a private constructor +struct XSpanInternalDummyArg final { + static forceinline constexpr XSpanInternalDummyArg make() noexcept { + return XSpanInternalDummyArg{}; + } +private: + explicit forceinline constexpr XSpanInternalDummyArg() noexcept {} +#if !(ACC_CC_MSC) // MSVC wants to use the copy and move constructors; correct or compiler bug? + // @COMPILER_BUG @MSVC_BUG + XSpanInternalDummyArg(const XSpanInternalDummyArg &) = delete; + XSpanInternalDummyArg(XSpanInternalDummyArg &&) noexcept = delete; + XSpanInternalDummyArg &operator=(const XSpanInternalDummyArg &) = delete; + XSpanInternalDummyArg &operator=(XSpanInternalDummyArg &&) noexcept = delete; +#endif +}; +#define XSpanInternalDummyArgInit \ + (XSPAN_NS(XSpanInternalDummyArg)(XSPAN_NS(XSpanInternalDummyArg)::make())) #endif // poison a pointer: point to a non-null invalid address @@ -209,7 +232,7 @@ struct XSpanInternalDummyArg { // - this should be efficient (so no mmap() guard page etc.) // - this should play nice with runtime checkers like ASAN, MSAN, valgrind, etc. // - this should play nice with static analyzers like clang-tidy etc. -static forceinline void *XSPAN_GET_POISON_VOID_PTR() { +static forceinline void *XSPAN_GET_POISON_VOID_PTR() noexcept { // return (void *) (upx_uintptr_t) 251; // NOLINT(performance-no-int-to-ptr) return (void *) 251; } diff --git a/src/util/xspan_impl_common.h b/src/util/xspan_impl_common.h index fe39210d..1f55697c 100644 --- a/src/util/xspan_impl_common.h +++ b/src/util/xspan_impl_common.h @@ -58,7 +58,7 @@ private: // debug - internal sanity check; also serves as pseudo-documentation #if DEBUG - noinline void assertInvariants() const { + noinline void assertInvariants() const may_throw { if __acc_cte (configRequirePtr) assert(ptr != nullptr); if __acc_cte (configRequireBase) @@ -68,7 +68,7 @@ private: xspan_check_range(ptr, base, size_in_bytes); } #else -forceinline void assertInvariants() const noexcept {} +forceinline constexpr void assertInvariants() const noexcept {} #endif static inline pointer makeNotNull(pointer p) { diff --git a/src/util/xspan_impl_ptr.h b/src/util/xspan_impl_ptr.h index af35b0f3..c5f04270 100644 --- a/src/util/xspan_impl_ptr.h +++ b/src/util/xspan_impl_ptr.h @@ -55,7 +55,7 @@ private: // inverse logic for ensuring valid pointers from existing objects inline pointer ensurePtr() const { return ptr; } // debug - inline void assertInvariants() const noexcept {} + forceinline constexpr void assertInvariants() const noexcept {} public: #if XSPAN_CONFIG_ENABLE_IMPLICIT_CONVERSION || 1