CI updates

This commit is contained in:
Markus F.X.J. Oberhumer 2025-08-04 16:05:44 +02:00 committed by Joe
parent 9866b9bca9
commit 2c79fa4fd0
15 changed files with 3249 additions and 342 deletions

View File

@ -99,9 +99,9 @@ jobs:
- run: uname -a; pwd; id; umask
- run: sudo apt-get update
- run: sudo apt-get install -y dmidecode gdb parallel valgrind
- run: sudo dmidecode | sed -n -e '/System Information/,/^$/p'
- run: sudo dmidecode -q
- run: sudo dmidecode
- run: (sudo dmidecode | sed -n -e '/System Information/,/^$/p') || true
- run: sudo dmidecode -q || true
- run: sudo dmidecode || true
- uses: actions/checkout@v4
with: { submodules: true }
- run: make build/extra/gcc/all
@ -119,6 +119,11 @@ jobs:
- name: ${{ format('Upload artifact {0}', env.artifact_name) }}
uses: actions/upload-artifact@v4
with: { name: '${{ env.artifact_name }}', path: tmp/artifact }
- name: Run install tests
run: |
jobs="gcc/debug gcc/release clang/debug clang/release"
echo "===== parallel jobs: $jobs"
DESTDIR="Install with make 2" parallel -kv --lb 'make build/extra/{}+install' ::: $jobs
- name: Mimic ctest tests SIGSEGV
run: |
jobs="gcc/debug gcc/release clang/debug clang/release"
@ -164,11 +169,11 @@ jobs:
ls -l /usr/bin/${f}*
done
ls -l /etc/alternatives/*mingw* || true
- run: sudo dmidecode | sed -n -e '/System Information/,/^$/p'
- run: (sudo dmidecode | sed -n -e '/System Information/,/^$/p') || true
if: ${{ matrix.use_extra }}
- run: sudo dmidecode -q
- run: sudo dmidecode -q || true
if: ${{ matrix.use_extra }}
- run: sudo dmidecode
- run: sudo dmidecode || true
if: ${{ matrix.use_extra }}
- name: Install Wine
if: ${{ matrix.use_extra && matrix.use_wine }}
@ -223,6 +228,10 @@ jobs:
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)
jobs="gcc/debug gcc/release clang/debug clang/release"
test "${{ matrix.use_extra }}" = "true" && jobs="$jobs gcc-m32/debug gcc-m32/release"
echo "===== parallel jobs: $jobs"
DESTDIR="Install with make 2" parallel -kv --lb 'make build/extra/{}+install' ::: $jobs
- name: Mimic ctest tests SIGSEGV
run: |
jobs="gcc/debug gcc/release clang/debug clang/release"
@ -571,7 +580,7 @@ jobs:
# only build a few selected targets => more targets are tested in the Weekly CI
- { zig_target: aarch64-linux-musl, qemu: qemu-aarch64 }
- { zig_target: aarch64-linux-musl, qemu: qemu-aarch64, zig_pic: -fPIE, container: 'alpine:3.18' }
- { zig_target: aarch64-macos.11.0-none }
- { zig_target: aarch64-macos.13.0-none }
- { zig_target: aarch64-windows-gnu }
- { zig_target: arm-linux-musleabihf, qemu: qemu-arm }
- { zig_target: armeb-linux-musleabihf, qemu: qemu-armeb }
@ -597,7 +606,7 @@ jobs:
- { zig_target: x86_64-linux-gnu.2.17, qemu: qemu-x86_64 } # can use QEMU because of gcompat
- { zig_target: x86_64-linux-musl, qemu: qemu-x86_64 }
- { zig_target: x86_64-linux-musl, qemu: qemu-x86_64, zig_pic: -fPIE, container: 'alpine:3.18' }
- { zig_target: x86_64-macos.11.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

55
.github/workflows/generate-doc.yml vendored Normal file
View File

@ -0,0 +1,55 @@
# Copyright (C) Markus Franz Xaver Johannes Oberhumer
# note: GitHub Actions runner images are frequently updated, and
# unfortunately this sometimes breaks builds in mysterious ways...
# see https://github.com/actions/runner-images.git
name: CI
on: [push, workflow_dispatch]
env:
CMAKE_REQUIRED_QUIET: 'OFF'
CMAKE_VERBOSE_MAKEFILE: 'ON'
CTEST_OUTPUT_ON_FAILURE: 'ON'
DEBIAN_FRONTEND: noninteractive
UPX_CMAKE_BUILD_FLAGS: --verbose
UPX_CMAKE_CONFIG_FLAGS: -Wdev --warn-uninitialized
UPX_CONFIG_HAVE_WORKING_BUILD_RPATH: 'ON'
UPX_DEBUG_TEST_FLOAT_DIVISION_BY_ZERO: 1
UPX_DEBUG_TEST_LIBC_QSORT: 1
ZSTD_CLEVEL: 9
# 2024-08-17
ZIG_DIST_VERSION: 0.14.0-dev.1166+bb7050106
jobs:
build-doc:
name: Rebuild stubs
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
submodules: false
fetch-depth: 0
- name: Install packages
run: |
sudo apt install --yes doxygen graphviz
- name: Build docs
run: doxygen doxygen-file
- uses: DenverCoder1/doxygen-github-pages-action@v2.0.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
folder: doc/html
config_file: doxygen-file
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@v4
with:
folder: doc/html
token: ${{ secrets.GITHUB_TOKEN }}

11
README
View File

@ -65,6 +65,17 @@ Please see the file UPX.DOC for the full documentation. The files
NEWS and BUGS also contain various tidbits of information.
DEVELOPPER API DOCUMENTATION
============================
The developper api internals of upx are available at [set the url there]()
Build it locally with:
```bash
doxygen doxygen-file
```
THE FUTURE
==========

270
doc/upx.1 generated
View File

@ -1,4 +1,3 @@
.\" -*- mode: troff; coding: utf-8 -*-
.\" Automatically generated by Pod::Man
.\"
.\" Standard preamble:
@ -16,12 +15,29 @@
.ft R
.fi
..
.\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>.
.\" Set up some character translations and predefined strings. \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote. \*(C+ will
.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
.\" nothing in troff, for use with C<>.
.tr \(*W-
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
. ds -- \(*W-
. ds PI pi
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
. ds L" ""
. ds R" ""
. ds C` ""
. ds C' ""
'br\}
.el\{\
. ds -- \|\(em\|
. ds PI \(*p
. ds L" ``
. ds R" ''
. ds C`
. ds C'
'br\}
@ -52,6 +68,68 @@
. \}
.\}
.rr rF
.\"
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
.\" Fear. Run. Save yourself. No user-serviceable parts.
. \" fudge factors for nroff and troff
.if n \{\
. ds #H 0
. ds #V .8m
. ds #F .3m
. ds #[ \f1
. ds #] \fP
.\}
.if t \{\
. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
. ds #V .6m
. ds #F 0
. ds #[ \&
. ds #] \&
.\}
. \" simple accents for nroff and troff
.if n \{\
. ds ' \&
. ds ` \&
. ds ^ \&
. ds , \&
. ds ~ ~
. ds /
.\}
.if t \{\
. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
.\}
. \" troff and (daisy-wheel) nroff accents
.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
.ds ae a\h'-(\w'a'u*4/10)'e
.ds Ae A\h'-(\w'A'u*4/10)'E
. \" corrections for vroff
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
. \" for low resolution devices (crt and lpr)
.if \n(.H>23 .if \n(.V>19 \
\{\
. ds : e
. ds 8 ss
. ds o a
. ds d- d\h'-1'\(ga
. ds D- D\h'-1'\(hy
. ds th \o'bp'
. ds Th \o'LP'
. ds ae ae
. ds Ae AE
.\}
.rm #[ #] #H #V #F C
.\" ========================================================================
.\"
.IX Title "UPX 1"
@ -60,12 +138,12 @@
.\" way too many mistakes in technical documents.
.if n .ad l
.nh
.SH NAME
.SH "NAME"
upx \- compress or expand executable files
.SH SYNOPSIS
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
\&\fBupx\fR [\ \fIcommand\fR\ ] [\ \fIoptions\fR\ ] \fIfilename\fR...
.SH ABSTRACT
.SH "ABSTRACT"
.IX Header "ABSTRACT"
.Vb 3
\& The Ultimate Packer for eXecutables
@ -73,27 +151,27 @@ upx \- compress or expand executable files
\& https://upx.github.io
.Ve
.PP
\&\fBUPX\fR is a portable, extendable, high-performance executable packer for
\&\fB\s-1UPX\s0\fR is a portable, extendable, high-performance executable packer for
several different executable formats. It achieves an excellent compression
ratio and offers \fI*very*\fR fast decompression. Your executables suffer
no memory overhead or other drawbacks for most of the formats supported,
because of in-place decompression.
.SH DISCLAIMER
.SH "DISCLAIMER"
.IX Header "DISCLAIMER"
\&\fBUPX\fR comes with ABSOLUTELY NO WARRANTY; for details see the file COPYING.
\&\fB\s-1UPX\s0\fR comes with \s-1ABSOLUTELY NO WARRANTY\s0; for details see the file \s-1COPYING.\s0
.PP
Please report all problems or suggestions to the authors. Thanks.
.SH "SECURITY CONTEXT"
.IX Header "SECURITY CONTEXT"
IMPORTANT NOTE: \fBUPX\fR inherits the security context of any files it handles.
\&\s-1IMPORTANT NOTE:\s0 \fB\s-1UPX\s0\fR inherits the security context of any files it handles.
.PP
This means that packing, unpacking, or even testing or listing a file requires
the same security considerations as actually executing the file.
.PP
Use \fBUPX\fR on trusted files only!
.SH DESCRIPTION
Use \fB\s-1UPX\s0\fR on trusted files only!
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
\&\fBUPX\fR is a versatile executable packer with the following features:
\&\fB\s-1UPX\s0\fR is a versatile executable packer with the following features:
.PP
.Vb 3
\& \- secure: as UPX is documented Open Source since many years any relevant
@ -126,32 +204,32 @@ Use \fBUPX\fR on trusted files only!
\& for commercial programs
.Ve
.PP
You probably understand now why we call \fBUPX\fR the "\fIultimate\fR"
You probably understand now why we call \fB\s-1UPX\s0\fR the "\fIultimate\fR"
executable packer.
.SH COMMANDS
.SH "COMMANDS"
.IX Header "COMMANDS"
.SS Compress
.SS "Compress"
.IX Subsection "Compress"
This is the default operation, eg. \fBupx yourfile.exe\fR will compress the file
specified on the command line.
.SS Decompress
.SS "Decompress"
.IX Subsection "Decompress"
All \fBUPX\fR supported file formats can be unpacked using the \fB\-d\fR switch, eg.
All \fB\s-1UPX\s0\fR supported file formats can be unpacked using the \fB\-d\fR switch, eg.
\&\fBupx \-d yourfile.exe\fR will uncompress the file you've just compressed.
.SS Test
.SS "Test"
.IX Subsection "Test"
The \fB\-t\fR command tests the integrity of the compressed and uncompressed
data, eg. \fBupx \-t yourfile.exe\fR check whether your file can be safely
decompressed. Note, that this command doesn't check the whole file, only
the part that will be uncompressed during program execution. This means
that you should not use this command instead of a virus checker.
.SS List
.SS "List"
.IX Subsection "List"
The \fB\-l\fR command prints out some information about the compressed files
specified on the command line as parameters, eg \fBupx \-l yourfile.exe\fR
shows the compressed / uncompressed size and the compression ratio of
\&\fIyourfile.exe\fR.
.SH OPTIONS
.SH "OPTIONS"
.IX Header "OPTIONS"
\&\fB\-q\fR: be quiet, suppress warnings
.PP
@ -161,10 +239,10 @@ shows the compressed / uncompressed size and the compression ratio of
.PP
\&\fB\-\-help\fR: prints the help
.PP
\&\fB\-\-version\fR: print the version of \fBUPX\fR
\&\fB\-\-version\fR: print the version of \fB\s-1UPX\s0\fR
.PP
\&\fB\-\-exact\fR: when compressing, require to be able to get a byte-identical file
after decompression with option \fB\-d\fR. [NOTE: this is work in progress and is
after decompression with option \fB\-d\fR. [\s-1NOTE:\s0 this is work in progress and is
not supported for all formats yet. If you do care, as a workaround you can
compress and then decompress your program a first time \- any further
compress-decompress steps should then yield byte-identical results
@ -177,16 +255,16 @@ as compared to the first decompressed version.]
[ ...more docs need to be written... \- type `\fBupx \-\-help\fR' for now ]
.SH "COMPRESSION LEVELS & TUNING"
.IX Header "COMPRESSION LEVELS & TUNING"
\&\fBUPX\fR offers ten different compression levels from \fB\-1\fR to \fB\-9\fR,
\&\fB\s-1UPX\s0\fR offers ten different compression levels from \fB\-1\fR to \fB\-9\fR,
and \fB\-\-best\fR. The default compression level is \fB\-8\fR for files
smaller than 512 KiB, and \fB\-7\fR otherwise.
.IP \(bu 4
.IP "\(bu" 4
Compression levels 1, 2 and 3 are pretty fast.
.IP \(bu 4
.IP "\(bu" 4
Compression levels 4, 5 and 6 achieve a good time/ratio performance.
.IP \(bu 4
.IP "\(bu" 4
Compression levels 7, 8 and 9 favor compression ratio over speed.
.IP \(bu 4
.IP "\(bu" 4
Compression level \fB\-\-best\fR may take a long time.
.PP
Note that compression level \fB\-\-best\fR can be somewhat slow for large
@ -194,28 +272,28 @@ files, but you definitely should use it when releasing a final version
of your program.
.PP
Quick info for achieving the best compression ratio:
.IP \(bu 4
.IP "\(bu" 4
Try \fBupx \-\-brute \-\-no\-lzma myfile.exe\fR or even
\&\fBupx \-\-ultra\-brute \-\-no\-lzma myfile.exe\fR.
.IP \(bu 4
The option \fB\-\-lzma\fR enables LZMA compression, which compresses better but
.IP "\(bu" 4
The option \fB\-\-lzma\fR enables \s-1LZMA\s0 compression, which compresses better but
is *significantly slower* at decompression. You probably do not want
to use it for large files.
.Sp
(Note that \fB\-\-lzma\fR is automatically enabled by \fB\-\-all\-methods\fR and
\&\fB\-\-brute\fR, use \fB\-\-no\-lzma\fR to override.)
.IP \(bu 4
.IP "\(bu" 4
Try if \fB\-\-overlay=strip\fR works.
.IP \(bu 4
.IP "\(bu" 4
For win32/pe programs there's \fB\-\-strip\-relocs=0\fR. See notes below.
.SH "OVERLAY HANDLING OPTIONS"
.IX Header "OVERLAY HANDLING OPTIONS"
Info: An "overlay" means auxiliary data attached after the logical end of
Info: An \*(L"overlay\*(R" 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).
.PP
\&\fBUPX\fR handles overlays like many other executable packers do: it simply
\&\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 overlaid data.
@ -231,8 +309,8 @@ actually accesses this overlaid data.
.Ve
.SH "ENVIRONMENT VARIABLE"
.IX Header "ENVIRONMENT VARIABLE"
The environment variable \fBUPX\fR can hold a set of default
options for \fBUPX\fR. These options are interpreted first and
The environment variable \fB\s-1UPX\s0\fR can hold a set of default
options for \fB\s-1UPX\s0\fR. These options are interpreted first and
can be overwritten by explicit command line parameters.
For example:
.PP
@ -243,18 +321,18 @@ For example:
.Ve
.PP
Under DOS/Windows you must use '#' instead of '=' when setting the
environment variable because of a COMMAND.COM limitation.
environment variable because of a \s-1COMMAND.COM\s0 limitation.
.PP
Not all of the options are valid in the environment variable \-
\&\fBUPX\fR will tell you.
\&\fB\s-1UPX\s0\fR will tell you.
.PP
You can explicitly use the \fB\-\-no\-env\fR option to ignore the
environment variable.
.SH "NOTES FOR THE SUPPORTED EXECUTABLE FORMATS"
.IX Header "NOTES FOR THE SUPPORTED EXECUTABLE FORMATS"
.SS "NOTES FOR ATARI/TOS"
.SS "\s-1NOTES FOR ATARI/TOS\s0"
.IX Subsection "NOTES FOR ATARI/TOS"
This is the executable format used by the Atari ST/TT, a Motorola 68000
This is the executable format used by the Atari \s-1ST/TT,\s0 a Motorola 68000
based personal computer which was popular in the late '80s. Support
of this format is only because of nostalgic feelings of one of
the authors and serves no practical purpose :\-).
@ -271,12 +349,12 @@ Extra options available for this executable format:
\& the compression ratio in some cases, but usually
\& the default method gives the best results anyway.
.Ve
.SS "NOTES FOR BVMLINUZ/I386"
.SS "\s-1NOTES FOR BVMLINUZ/I386\s0"
.IX Subsection "NOTES FOR BVMLINUZ/I386"
Same as vmlinuz/i386.
.SS "NOTES FOR DOS/COM"
.SS "\s-1NOTES FOR DOS/COM\s0"
.IX Subsection "NOTES FOR DOS/COM"
Obviously \fBUPX\fR won't work with executables that want to read data from
Obviously \fB\s-1UPX\s0\fR won't work with executables that want to read data from
themselves (like some commandline utilities that ship with Win95/98/ME).
.PP
Compressed programs only work on a 286+.
@ -300,11 +378,11 @@ Extra options available for this executable format:
\& the compression ratio in some cases, but usually
\& the default filter gives the best results anyway.
.Ve
.SS "NOTES FOR DOS/EXE"
.SS "\s-1NOTES FOR DOS/EXE\s0"
.IX Subsection "NOTES FOR DOS/EXE"
dos/exe stands for all "normal" 16\-bit DOS executables.
dos/exe stands for all \*(L"normal\*(R" 16\-bit \s-1DOS\s0 executables.
.PP
Obviously \fBUPX\fR won't work with executables that want to read data from
Obviously \fB\s-1UPX\s0\fR won't work with executables that want to read data from
themselves (like some command line utilities that ship with Win95/98/ME).
.PP
Compressed programs only work on a 286+.
@ -321,7 +399,7 @@ Extra options available for this executable format:
\& the compression ratio in some cases, but usually
\& the default method gives the best results anyway.
.Ve
.SS "NOTES FOR DOS/SYS"
.SS "\s-1NOTES FOR DOS/SYS\s0"
.IX Subsection "NOTES FOR DOS/SYS"
Compressed programs only work on a 286+.
.PP
@ -344,20 +422,20 @@ Extra options available for this executable format:
\& the compression ratio in some cases, but usually
\& the default filter gives the best results anyway.
.Ve
.SS "NOTES FOR DJGPP2/COFF"
.SS "\s-1NOTES FOR DJGPP2/COFF\s0"
.IX Subsection "NOTES FOR DJGPP2/COFF"
First of all, it is recommended to use \fBUPX\fR *instead* of \fBstrip\fR. strip has
First of all, it is recommended to use \fB\s-1UPX\s0\fR *instead* of \fBstrip\fR. strip has
the very bad habit of replacing your stub with its own (outdated) version.
Additionally \fBUPX\fR corrects a bug/feature in strip v2.8.x: it
Additionally \fB\s-1UPX\s0\fR corrects a bug/feature in strip v2.8.x: it
will fix the 4 KiB alignment of the stub.
.PP
\&\fBUPX\fR includes the full functionality of stubify. This means it will
automatically stubify your COFF files. Use the option \fB\-\-coff\fR to
\&\fB\s-1UPX\s0\fR includes the full functionality of stubify. This means it will
automatically stubify your \s-1COFF\s0 files. Use the option \fB\-\-coff\fR to
disable this functionality (see below).
.PP
\&\fBUPX\fR automatically handles Allegro packfiles.
\&\fB\s-1UPX\s0\fR automatically handles Allegro packfiles.
.PP
The DLM format (a rather exotic shared library extension) is not supported.
The \s-1DLM\s0 format (a rather exotic shared library extension) is not supported.
.PP
Packed programs will be byte-identical to the original after uncompression.
All debug information and trailing garbage will be stripped, though.
@ -378,7 +456,7 @@ Extra options available for this executable format:
\& the compression ratio in some cases, but usually
\& the default filter gives the best results anyway.
.Ve
.SS "NOTES FOR LINUX [general]"
.SS "\s-1NOTES FOR LINUX\s0 [general]"
.IX Subsection "NOTES FOR LINUX [general]"
Introduction
.PP
@ -515,15 +593,15 @@ General notes:
\& been modified after compression.
\& Running \`strace \-o strace.log compressed_file\*(Aq will tell you more.
.Ve
.SS "NOTES FOR LINUX/ELF386"
.SS "\s-1NOTES FOR LINUX/ELF386\s0"
.IX Subsection "NOTES FOR LINUX/ELF386"
Please read the general Linux description first.
.PP
The linux/elf386 format decompresses directly into RAM,
The linux/elf386 format decompresses directly into \s-1RAM,\s0
uses only one exec, does not use space in /tmp,
and does not use /proc.
.PP
Linux/elf386 is automatically selected for Linux ELF executables.
Linux/elf386 is automatically selected for Linux \s-1ELF\s0 executables.
.PP
Packed programs will be byte-identical to the original after uncompression.
.PP
@ -563,12 +641,12 @@ Extra options available for this executable format:
.Vb 1
\& (none)
.Ve
.SS "NOTES FOR LINUX/SH386"
.SS "\s-1NOTES FOR LINUX/SH386\s0"
.IX Subsection "NOTES FOR LINUX/SH386"
Please read the general Linux description first.
.PP
Shell scripts where the underling shell accepts a ``\-c'' argument
can use the Linux/sh386 format. \fBUPX\fR decompresses the shell script
can use the Linux/sh386 format. \fB\s-1UPX\s0\fR decompresses the shell script
into low memory, then maps the shell and passes the entire text of the
script as an argument with a leading ``\-c''.
It does not use space in /tmp, and does not use /proc.
@ -613,7 +691,7 @@ Extra options available for this executable format:
.Vb 1
\& (none)
.Ve
.SS "NOTES FOR LINUX/386"
.SS "\s-1NOTES FOR LINUX/386\s0"
.IX Subsection "NOTES FOR LINUX/386"
Please read the general Linux description first.
.PP
@ -686,10 +764,10 @@ Extra options available for this executable format:
\& format, i.e. do not try the linux/elf386 and
\& linux/sh386 formats.
.Ve
.SS "NOTES FOR PS1/EXE"
.SS "\s-1NOTES FOR PS1/EXE\s0"
.IX Subsection "NOTES FOR PS1/EXE"
This is the executable format used by the Sony PlayStation (PSone),
a MIPS R3000 based gaming console which is popular since the late '90s.
a \s-1MIPS R3000\s0 based gaming console which is popular since the late '90s.
Support of this format is very similar to the Atari one, because of
nostalgic feelings of one of the authors.
.PP
@ -738,12 +816,12 @@ Extra options available for this executable format:
\& but the compressed executable will not boot from a CD.
\& Use it for console transfer only !
.Ve
.SS "NOTES FOR RTM32/PE and ARM/PE"
.SS "\s-1NOTES FOR RTM32/PE\s0 and \s-1ARM/PE\s0"
.IX Subsection "NOTES FOR RTM32/PE and ARM/PE"
Same as win32/pe.
.SS "NOTES FOR TMT/ADAM"
.SS "\s-1NOTES FOR TMT/ADAM\s0"
.IX Subsection "NOTES FOR TMT/ADAM"
This format is used by the TMT Pascal compiler \- see http://www.tmt.com/ .
This format is used by the \s-1TMT\s0 Pascal compiler \- see http://www.tmt.com/ .
.PP
Extra options available for this executable format:
.PP
@ -758,11 +836,11 @@ Extra options available for this executable format:
\& the compression ratio in some cases, but usually
\& the default filter gives the best results anyway.
.Ve
.SS "NOTES FOR VMLINUZ/386"
.SS "\s-1NOTES FOR VMLINUZ/386\s0"
.IX Subsection "NOTES FOR VMLINUZ/386"
The vmlinuz/386 and bvmlinuz/386 formats take a gzip-compressed
bootable Linux kernel image ("vmlinuz", "zImage", "bzImage"),
gzip-decompress it and re-compress it with the \fBUPX\fR compression method.
bootable Linux kernel image (\*(L"vmlinuz\*(R", \*(L"zImage\*(R", \*(L"bzImage\*(R"),
gzip-decompress it and re-compress it with the \fB\s-1UPX\s0\fR compression method.
.PP
vmlinuz/386 is completely unrelated to the other Linux executable
formats, and it does not share any of their drawbacks.
@ -811,14 +889,14 @@ Extra options available for this executable format:
\& the compression ratio in some cases, but usually
\& the default filter gives the best results anyway.
.Ve
.SS "NOTES FOR WATCOM/LE"
.SS "\s-1NOTES FOR WATCOM/LE\s0"
.IX Subsection "NOTES FOR WATCOM/LE"
\&\fBUPX\fR has been successfully tested with the following extenders:
DOS4G, DOS4GW, PMODE/W, DOS32a, CauseWay.
The WDOS/X extender is partly supported (for details
see the file bugs BUGS).
\&\fB\s-1UPX\s0\fR has been successfully tested with the following extenders:
\s-1DOS4G, DOS4GW, PMODE/W,\s0 DOS32a, CauseWay.
The \s-1WDOS/X\s0 extender is partly supported (for details
see the file bugs \s-1BUGS\s0).
.PP
DLLs and the LX format are not supported.
DLLs and the \s-1LX\s0 format are not supported.
.PP
Extra options available for this executable format:
.PP
@ -826,12 +904,12 @@ Extra options available for this executable format:
\& \-\-le Produce an unbound LE output instead of
\& keeping the current stub.
.Ve
.SS "NOTES FOR WIN32/PE"
.SS "\s-1NOTES FOR WIN32/PE\s0"
.IX Subsection "NOTES FOR WIN32/PE"
The PE support in \fBUPX\fR is quite stable now, but probably there are
The \s-1PE\s0 support in \fB\s-1UPX\s0\fR is quite stable now, but probably there are
still some incompatibilities with some files.
.PP
Because of the way \fBUPX\fR (and other packers for this format) works, you
Because of the way \fB\s-1UPX\s0\fR (and other packers for this format) works, you
can see increased memory usage of your compressed files because the whole
program is loaded into memory at startup.
If you start several instances of huge compressed programs you're
@ -844,17 +922,17 @@ smaller, but it's still there.
If you're running executables from network, then compressed programs
will load faster, and require less bandwidth during execution.
.PP
DLLs are supported. But UPX compressed DLLs can not share common data and
DLLs are supported. But \s-1UPX\s0 compressed DLLs can not share common data and
code when they got used by multiple applications. So compressing msvcrt.dll
is a waste of memory, but compressing the dll plugins of a particular
application may be a better idea.
.PP
Screensavers are supported, with the restriction that the filename
must end with ".scr" (as screensavers are handled slightly different
must end with \*(L".scr\*(R" (as screensavers are handled slightly different
than normal exe files).
.PP
UPX compressed PE files have some minor memory overhead (usually in the
10 \- 30 KiB range) which can be seen by specifying the "\-i" command
\&\s-1UPX\s0 compressed \s-1PE\s0 files have some minor memory overhead (usually in the
10 \- 30 KiB range) which can be seen by specifying the \*(L"\-i\*(R" command
line switch during compression.
.PP
Extra options available for this executable format:
@ -918,16 +996,16 @@ Extra options available for this executable format:
\& the compression ratio in some cases, but usually
\& the default filter gives the best results anyway.
.Ve
.SH DIAGNOSTICS
.SH "DIAGNOSTICS"
.IX Header "DIAGNOSTICS"
Exit status is normally 0; if an error occurs, exit status
is 1. If a warning occurs, exit status is 2.
.PP
\&\fBUPX\fR's diagnostics are intended to be self-explanatory.
.SH BUGS
\&\fB\s-1UPX\s0\fR's diagnostics are intended to be self-explanatory.
.SH "BUGS"
.IX Header "BUGS"
Please report all bugs immediately to the authors.
.SH AUTHORS
.SH "AUTHORS"
.IX Header "AUTHORS"
.Vb 2
\& Markus F.X.J. Oberhumer <markus@oberhumer.com>
@ -937,7 +1015,7 @@ Please report all bugs immediately to the authors.
\&
\& John F. Reiser <jreiser@BitWagon.com>
.Ve
.SH COPYRIGHT
.SH "COPYRIGHT"
.IX Header "COPYRIGHT"
Copyright (C) 1996\-2025 Markus Franz Xaver Johannes Oberhumer
.PP
@ -945,16 +1023,16 @@ Copyright (C) 1996\-2025 Laszlo Molnar
.PP
Copyright (C) 2000\-2025 John F. Reiser
.PP
\&\fBUPX\fR is distributed with full source code under the terms of the
GNU General Public License v2+; either under the pure GPLv2+ (see
the file COPYING), or (at your option) under the GPLv+2 with special
\&\fB\s-1UPX\s0\fR is distributed with full source code under the terms of the
\&\s-1GNU\s0 General Public License v2+; either under the pure GPLv2+ (see
the file \s-1COPYING\s0), or (at your option) under the GPLv+2 with special
exceptions and restrictions granting the free usage for all binaries
including commercial programs (see the file LICENSE).
including commercial programs (see the file \s-1LICENSE\s0).
.PP
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.
but \s-1WITHOUT ANY WARRANTY\s0; without even the implied warranty of
\&\s-1MERCHANTABILITY\s0 or \s-1FITNESS FOR A PARTICULAR PURPOSE.\s0
.PP
You should have received a copy of the UPX License Agreements along
with this program; see the files COPYING and LICENSE. If not,
visit the UPX home page.
You should have received a copy of the \s-1UPX\s0 License Agreements along
with this program; see the files \s-1COPYING\s0 and \s-1LICENSE.\s0 If not,
visit the \s-1UPX\s0 home page.

2688
doxygen-file Normal file

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@ __add_cmake_config() {
}
# pass common CMake settings
for v in CMAKE_VERBOSE_MAKEFILE; do
for v in CMAKE_INSTALL_PREFIX CMAKE_VERBOSE_MAKEFILE; do
__add_cmake_config $v
done
# pass common CMake toolchain settings

View File

@ -29,6 +29,6 @@ fi
# limit memory usage to 1 GiB (in case of clang-format problems with invalid files)
ulimit -v 1048576 || true
#echo $UPX_CLANG_FORMAT
#echo "$UPX_CLANG_FORMAT"
exec "$UPX_CLANG_FORMAT" -style=file "$@"
exit 99

View File

@ -210,7 +210,7 @@ private:
UPX_CXX_DISABLE_NEW_DELETE(LEPolicy)
};
// Native Endianness policy (aka host policy)
// Native Endianness policy (aka Host Policy)
#if (ACC_ABI_BIG_ENDIAN)
typedef BEPolicy NEPolicy;
typedef BEPolicy HostPolicy;

View File

@ -200,15 +200,15 @@ noreturn 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 <>
noreturn void throwCantPack(const char *format, ...) may_throw attribute_format(1, 2);
template <class T>
void throwCantUnpack(const T *, ...) DELETED_FUNCTION;
template <>
noreturn void throwCantUnpack(const char *format, ...) may_throw attribute_format(1, 2);
template <class T>
void throwInternalError(const T *, ...) DELETED_FUNCTION;
template <>
noreturn void throwCantPack(const char *format, ...) may_throw attribute_format(1, 2);
template <>
noreturn void throwCantUnpack(const char *format, ...) may_throw attribute_format(1, 2);
template <>
noreturn void throwInternalError(const char *format, ...) may_throw attribute_format(1, 2);
/* vim:set ts=4 sw=4 et: */

View File

@ -48,7 +48,7 @@ protected:
public:
virtual ~PackerBase() noexcept {}
// getVersion() enables detecting forward incompatibility of unpack()
// by old upx when newer upx changes the format of compressed output.
// by old UPX when newer UPX changes the format of compressed output.
virtual int getVersion() const = 0;
// A unique integer ID for this executable format; see UPX_F_xxx in conf.h.
virtual int getFormat() const = 0;
@ -58,11 +58,11 @@ public:
virtual const int *getFilters() const = 0;
// canPack() should throw a cantPackException explaining why it cannot pack
// a recognized format.
// a recognized format.
// canPack() can also return -1 to fail early; see class PackMaster
virtual tribool canPack() = 0;
// canUnpack() should throw a cantUnpackException explaining why it cannot unpack
// a recognized format.
// a recognized format.
// canUnpack() can also return -1 to fail early; see class PackMaster
virtual tribool canUnpack() = 0;

View File

@ -2281,9 +2281,46 @@ void PeFile::callProcessResources(Resource &res, unsigned &ic) {
ic += soresources;
}
template <typename LEXX, typename ht>
void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask,
upx_uint64_t default_imagebase, bool last_section_rsrc_only) {
/**
* @brief create UPX0 section
*
* @name pack0
*
* Reduct the file size.
*
* @param fo
* The OutputFile class to the path where the new file will be created.
*
* @param ih
* Input PE header.
*
* Native windows data structure required by the os to be understood and to make a valid executable. The documentation of this data type is present there: https://www.vergiliusproject.com/kernels/x64/windows-11/23h2/_IMAGE_FILE_HEADER and described there: https://wiki.osdev.org/PE#PE_header .
*
* @param oh
* Output PE header.
*
* Native windows data structure required by the os to be understood and to make a valid executable. The documentation of this data type is present there: https://www.vergiliusproject.com/kernels/x64/windows-11/23h2/_IMAGE_FILE_HEADER and described there: https://wiki.osdev.org/PE#PE_header .
*
* @param subsystem_mask
* Permission mask for UPX0, UPX1, etc... sections.
*
* Number between 0 and 255 to indicate the section permissions of the section UPX0, UPX1, etc...
*
* @param default_imagebase
* Base address of the image base of the process.
*
* Very first start of where is stored the data and the code run by the OS.
*
* @param last_section_rsrc_only
* This is true when the last PE section of the compressed file must only contain resources and must be called "rsrc"
*
* @return void, in any circonstance.
*
* @remarks None.
*
*/
template <typename LEXX, typename ht> void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask, upx_uint64_t default_imagebase, bool last_section_rsrc_only) {
// FIXME: we need to think about better support for --exact
if (opt->exact)
throwCantPackExact();

View File

@ -27,10 +27,6 @@
#pragma once
/*************************************************************************
// general/pe handling
**************************************************************************/
class PeFile : public Packer {
typedef Packer super;
public:
@ -65,9 +61,39 @@ protected:
virtual void setOhDataBase(const pe_section_t *osection) = 0;
virtual void setOhHeaderSize(const pe_section_t *osection) = 0;
template <typename LEXX, typename ht>
void pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask,
upx_uint64_t default_imagebase, bool last_section_rsrc_only);
/**
* \brief create UPX0 section
*
*
* \param fo
* The OutputFile class to the path where the new file will be created.
*
* \param ih
* Input handler.
*
* \param oh
* Output handler.
*
* \param subsystem_mask
* Permission mask for UPX0, UPX1, etc... sections.
*
* Number between 0 and 255 to indicate the section permissions of the section UPX0, UPX1, etc...
*
* \param default_imagebase
* Base address of the image base of the process.
*
* Very first start of where is stored the data and the code run by the OS.
*
* \param last_section_rsrc_only
* true if
*
* \return void, in any circonstance.
*
*
**/
template <typename LEXX, typename ht> void pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask, upx_uint64_t default_imagebase, bool last_section_rsrc_only);
template <typename ht, typename LEXX, typename ord_mask_t>
void unpack0(OutputFile *fo, const ht &ih, ht &oh, ord_mask_t ord_mask, bool set_oft);

View File

@ -552,6 +552,7 @@ amd64-win64.pe.h : tc_objdump_disasm_options = -M intel-mnemonic
tc.amd64-win64.pe.gcc = amd64-linux-gcc-4.1.1 -m64 -nostdinc -DWINDOWS_BACK=1 -MMD -MT $@
tc.amd64-win64.pe.gcc += -fno-exceptions -fno-asynchronous-unwind-tables
tc.amd64-win64.pe.gcc += -mno-red-zone
tc.amd64-win64.pe.gcc += -Wall -W -Wcast-align -Wcast-qual -Wstrict-prototypes -Wwrite-strings -Werror
tc.amd64-win64.pe.objdump = multiarch-objdump-2.23.90

View File

@ -33,6 +33,222 @@
namespace upx {
/*************************************************************************
// compile_time
**************************************************************************/
namespace compile_time {
constexpr std::size_t string_len(const char *a) noexcept {
return *a == '\0' ? 0 : 1 + string_len(a + 1);
}
constexpr bool string_eq(const char *a, const char *b) noexcept {
return *a == *b && (*a == '\0' || string_eq(a + 1, b + 1));
}
constexpr bool string_lt(const char *a, const char *b) noexcept {
return (uchar) *a < (uchar) *b || (*a != '\0' && *a == *b && string_lt(a + 1, b + 1));
}
forceinline constexpr bool string_ne(const char *a, const char *b) noexcept {
return !string_eq(a, b);
}
forceinline constexpr bool string_gt(const char *a, const char *b) noexcept {
return string_lt(b, a);
}
forceinline constexpr bool string_le(const char *a, const char *b) noexcept {
return !string_lt(b, a);
}
forceinline constexpr bool string_ge(const char *a, const char *b) noexcept {
return !string_lt(a, b);
}
constexpr bool mem_eq(const char *a, const char *b, std::size_t n) noexcept {
return n == 0 || (*a == *b && mem_eq(a + 1, b + 1, n - 1));
}
constexpr bool mem_eq(const unsigned char *a, const unsigned char *b, std::size_t n) noexcept {
return n == 0 || (*a == *b && mem_eq(a + 1, b + 1, n - 1));
}
constexpr bool mem_eq(const char *a, const unsigned char *b, std::size_t n) noexcept {
return n == 0 || ((uchar) *a == *b && mem_eq(a + 1, b + 1, n - 1));
}
constexpr bool mem_eq(const unsigned char *a, const char *b, std::size_t n) noexcept {
return n == 0 || (*a == (uchar) *b && mem_eq(a + 1, b + 1, n - 1));
}
constexpr void mem_set(char *p, char c, std::size_t n) noexcept {
(void) (n == 0 || (*p = c, mem_set(p + 1, c, n - 1), 0));
}
constexpr void mem_set(unsigned char *p, unsigned char c, std::size_t n) noexcept {
(void) (n == 0 || (*p = c, mem_set(p + 1, c, n - 1), 0));
}
forceinline constexpr void mem_clear(char *p, std::size_t n) noexcept { mem_set(p, (char) 0, n); }
forceinline constexpr void mem_clear(unsigned char *p, std::size_t n) noexcept {
mem_set(p, (unsigned char) 0, n);
}
forceinline constexpr upx_uint16_t bswap16(upx_uint16_t v) noexcept {
typedef unsigned U;
return (upx_uint16_t) ((((U) v >> 8) & 0xff) | (((U) v & 0xff) << 8));
}
forceinline constexpr upx_uint32_t bswap32(upx_uint32_t v) noexcept {
typedef upx_uint32_t U;
return (upx_uint32_t) ((((U) v >> 24) & 0xff) | (((U) v >> 8) & 0xff00) |
(((U) v & 0xff00) << 8) | (((U) v & 0xff) << 24));
}
forceinline constexpr upx_uint64_t bswap64(upx_uint64_t v) noexcept {
return (upx_uint64_t) (((upx_uint64_t) bswap32((upx_uint32_t) v) << 32) |
bswap32((upx_uint32_t) (v >> 32)));
}
forceinline constexpr upx_uint16_t get_be16(const byte *p) noexcept {
typedef unsigned U;
return (upx_uint16_t) (((U) p[0] << 8) | ((U) p[1] << 0));
}
forceinline constexpr upx_uint32_t get_be24(const byte *p) noexcept {
typedef upx_uint32_t U;
return (upx_uint32_t) (((U) p[0] << 16) | ((U) p[1] << 8) | ((U) p[2] << 0));
}
forceinline constexpr upx_uint32_t get_be32(const byte *p) noexcept {
typedef upx_uint32_t U;
return (upx_uint32_t) (((U) p[0] << 24) | ((U) p[1] << 16) | ((U) p[2] << 8) | ((U) p[3] << 0));
}
forceinline constexpr upx_uint64_t get_be64(const byte *p) noexcept {
typedef upx_uint64_t U;
return (upx_uint64_t) (((U) p[0] << 56) | ((U) p[1] << 48) | ((U) p[2] << 40) |
((U) p[3] << 32) | ((U) p[4] << 24) | ((U) p[5] << 16) |
((U) p[6] << 8) | ((U) p[7] << 0));
}
forceinline constexpr void set_be16(byte *p, upx_uint16_t v) noexcept {
p[0] = (byte) ((v >> 8) & 0xff);
p[1] = (byte) ((v >> 0) & 0xff);
}
forceinline constexpr void set_be24(byte *p, upx_uint32_t v) noexcept {
p[0] = (byte) ((v >> 16) & 0xff);
p[1] = (byte) ((v >> 8) & 0xff);
p[2] = (byte) ((v >> 0) & 0xff);
}
forceinline constexpr void set_be32(byte *p, upx_uint32_t v) noexcept {
p[0] = (byte) ((v >> 24) & 0xff);
p[1] = (byte) ((v >> 16) & 0xff);
p[2] = (byte) ((v >> 8) & 0xff);
p[3] = (byte) ((v >> 0) & 0xff);
}
forceinline constexpr void set_be64(byte *p, upx_uint64_t v) noexcept {
p[0] = (byte) ((v >> 56) & 0xff);
p[1] = (byte) ((v >> 48) & 0xff);
p[2] = (byte) ((v >> 40) & 0xff);
p[3] = (byte) ((v >> 32) & 0xff);
p[4] = (byte) ((v >> 24) & 0xff);
p[5] = (byte) ((v >> 16) & 0xff);
p[6] = (byte) ((v >> 8) & 0xff);
p[7] = (byte) ((v >> 0) & 0xff);
}
forceinline constexpr upx_uint16_t get_le16(const byte *p) noexcept {
typedef unsigned U;
return (upx_uint16_t) (((U) p[0] << 0) | ((U) p[1] << 8));
}
forceinline constexpr upx_uint32_t get_le24(const byte *p) noexcept {
typedef upx_uint32_t U;
return (upx_uint32_t) (((U) p[0] << 0) | ((U) p[1] << 8) | ((U) p[2] << 16));
}
forceinline constexpr upx_uint32_t get_le32(const byte *p) noexcept {
typedef upx_uint32_t U;
return (upx_uint32_t) (((U) p[0] << 0) | ((U) p[1] << 8) | ((U) p[2] << 16) | ((U) p[3] << 24));
}
forceinline constexpr upx_uint64_t get_le64(const byte *p) noexcept {
typedef upx_uint64_t U;
return (upx_uint64_t) (((U) p[0] << 0) | ((U) p[1] << 8) | ((U) p[2] << 16) | ((U) p[3] << 24) |
((U) p[4] << 32) | ((U) p[5] << 40) | ((U) p[6] << 48) |
((U) p[7] << 56));
}
forceinline constexpr void set_le16(byte *p, upx_uint16_t v) noexcept {
p[0] = (byte) ((v >> 0) & 0xff);
p[1] = (byte) ((v >> 8) & 0xff);
}
forceinline constexpr void set_le24(byte *p, upx_uint32_t v) noexcept {
p[0] = (byte) ((v >> 0) & 0xff);
p[1] = (byte) ((v >> 8) & 0xff);
p[2] = (byte) ((v >> 16) & 0xff);
}
forceinline constexpr void set_le32(byte *p, upx_uint32_t v) noexcept {
p[0] = (byte) ((v >> 0) & 0xff);
p[1] = (byte) ((v >> 8) & 0xff);
p[2] = (byte) ((v >> 16) & 0xff);
p[3] = (byte) ((v >> 24) & 0xff);
}
forceinline constexpr void set_le64(byte *p, upx_uint64_t v) noexcept {
p[0] = (byte) ((v >> 0) & 0xff);
p[1] = (byte) ((v >> 8) & 0xff);
p[2] = (byte) ((v >> 16) & 0xff);
p[3] = (byte) ((v >> 24) & 0xff);
p[4] = (byte) ((v >> 32) & 0xff);
p[5] = (byte) ((v >> 40) & 0xff);
p[6] = (byte) ((v >> 48) & 0xff);
p[7] = (byte) ((v >> 56) & 0xff);
}
forceinline constexpr upx_uint16_t get_ne16(const byte *p) noexcept {
#if (ACC_ABI_BIG_ENDIAN)
return get_be16(p);
#else
return get_le16(p);
#endif
}
forceinline constexpr upx_uint32_t get_ne24(const byte *p) noexcept {
#if (ACC_ABI_BIG_ENDIAN)
return get_be24(p);
#else
return get_le24(p);
#endif
}
forceinline constexpr upx_uint32_t get_ne32(const byte *p) noexcept {
#if (ACC_ABI_BIG_ENDIAN)
return get_be32(p);
#else
return get_le32(p);
#endif
}
forceinline constexpr upx_uint64_t get_ne64(const byte *p) noexcept {
#if (ACC_ABI_BIG_ENDIAN)
return get_be64(p);
#else
return get_le64(p);
#endif
}
forceinline constexpr void set_ne16(byte *p, upx_uint16_t v) noexcept {
#if (ACC_ABI_BIG_ENDIAN)
set_be16(p, v);
#else
set_le16(p, v);
#endif
}
forceinline constexpr void set_ne24(byte *p, upx_uint32_t v) noexcept {
#if (ACC_ABI_BIG_ENDIAN)
set_be24(p, v);
#else
set_le24(p, v);
#endif
}
forceinline constexpr void set_ne32(byte *p, upx_uint32_t v) noexcept {
#if (ACC_ABI_BIG_ENDIAN)
set_be32(p, v);
#else
set_le32(p, v);
#endif
}
forceinline constexpr void set_ne64(byte *p, upx_uint64_t v) noexcept {
#if (ACC_ABI_BIG_ENDIAN)
set_be64(p, v);
#else
set_le64(p, v);
#endif
}
} // namespace compile_time
/*************************************************************************
// core util
**************************************************************************/
@ -340,6 +556,7 @@ forceinline T atomic_exchange(T *ptr, T new_value) noexcept {
// helper classes so we don't leak memory on exceptions
template <class T>
struct ObjectDeleter final {
static_assert(std::is_nothrow_destructible_v<T>);
T **items; // public
std::size_t count; // public
explicit ObjectDeleter(T **p, std::size_t n) noexcept : items(p), count(n) {}
@ -350,10 +567,10 @@ struct ObjectDeleter final {
delete item; // single object delete
}
}
static_assert(std::is_nothrow_destructible_v<T>);
};
template <class T>
struct ArrayDeleter final {
static_assert(std::is_nothrow_destructible_v<T>);
T **items; // public
std::size_t count; // public
explicit ArrayDeleter(T **p, std::size_t n) noexcept : items(p), count(n) {}
@ -364,7 +581,6 @@ struct ArrayDeleter final {
delete[] item; // array delete
}
}
static_assert(std::is_nothrow_destructible_v<T>);
};
template <class T>
struct MallocDeleter final {
@ -380,222 +596,6 @@ struct MallocDeleter final {
}
};
/*************************************************************************
// compile_time
**************************************************************************/
namespace compile_time {
constexpr std::size_t string_len(const char *a) noexcept {
return *a == '\0' ? 0 : 1 + string_len(a + 1);
}
constexpr bool string_eq(const char *a, const char *b) noexcept {
return *a == *b && (*a == '\0' || string_eq(a + 1, b + 1));
}
constexpr bool string_lt(const char *a, const char *b) noexcept {
return (uchar) *a < (uchar) *b || (*a != '\0' && *a == *b && string_lt(a + 1, b + 1));
}
forceinline constexpr bool string_ne(const char *a, const char *b) noexcept {
return !string_eq(a, b);
}
forceinline constexpr bool string_gt(const char *a, const char *b) noexcept {
return string_lt(b, a);
}
forceinline constexpr bool string_le(const char *a, const char *b) noexcept {
return !string_lt(b, a);
}
forceinline constexpr bool string_ge(const char *a, const char *b) noexcept {
return !string_lt(a, b);
}
constexpr bool mem_eq(const char *a, const char *b, std::size_t n) noexcept {
return n == 0 || (*a == *b && mem_eq(a + 1, b + 1, n - 1));
}
constexpr bool mem_eq(const unsigned char *a, const unsigned char *b, std::size_t n) noexcept {
return n == 0 || (*a == *b && mem_eq(a + 1, b + 1, n - 1));
}
constexpr bool mem_eq(const char *a, const unsigned char *b, std::size_t n) noexcept {
return n == 0 || ((uchar) *a == *b && mem_eq(a + 1, b + 1, n - 1));
}
constexpr bool mem_eq(const unsigned char *a, const char *b, std::size_t n) noexcept {
return n == 0 || (*a == (uchar) *b && mem_eq(a + 1, b + 1, n - 1));
}
constexpr void mem_set(char *p, char c, std::size_t n) noexcept {
(void) (n == 0 || (*p = c, mem_set(p + 1, c, n - 1), 0));
}
constexpr void mem_set(unsigned char *p, unsigned char c, std::size_t n) noexcept {
(void) (n == 0 || (*p = c, mem_set(p + 1, c, n - 1), 0));
}
forceinline constexpr void mem_clear(char *p, std::size_t n) noexcept { mem_set(p, (char) 0, n); }
forceinline constexpr void mem_clear(unsigned char *p, std::size_t n) noexcept {
mem_set(p, (unsigned char) 0, n);
}
forceinline constexpr upx_uint16_t bswap16(upx_uint16_t v) noexcept {
typedef unsigned U;
return (upx_uint16_t) ((((U) v >> 8) & 0xff) | (((U) v & 0xff) << 8));
}
forceinline constexpr upx_uint32_t bswap32(upx_uint32_t v) noexcept {
typedef upx_uint32_t U;
return (upx_uint32_t) ((((U) v >> 24) & 0xff) | (((U) v >> 8) & 0xff00) |
(((U) v & 0xff00) << 8) | (((U) v & 0xff) << 24));
}
forceinline constexpr upx_uint64_t bswap64(upx_uint64_t v) noexcept {
return (upx_uint64_t) (((upx_uint64_t) bswap32((upx_uint32_t) v) << 32) |
bswap32((upx_uint32_t) (v >> 32)));
}
forceinline constexpr upx_uint16_t get_be16(const byte *p) noexcept {
typedef unsigned U;
return (upx_uint16_t) (((U) p[0] << 8) | ((U) p[1] << 0));
}
forceinline constexpr upx_uint32_t get_be24(const byte *p) noexcept {
typedef upx_uint32_t U;
return (upx_uint32_t) (((U) p[0] << 16) | ((U) p[1] << 8) | ((U) p[2] << 0));
}
forceinline constexpr upx_uint32_t get_be32(const byte *p) noexcept {
typedef upx_uint32_t U;
return (upx_uint32_t) (((U) p[0] << 24) | ((U) p[1] << 16) | ((U) p[2] << 8) | ((U) p[3] << 0));
}
forceinline constexpr upx_uint64_t get_be64(const byte *p) noexcept {
typedef upx_uint64_t U;
return (upx_uint64_t) (((U) p[0] << 56) | ((U) p[1] << 48) | ((U) p[2] << 40) |
((U) p[3] << 32) | ((U) p[4] << 24) | ((U) p[5] << 16) |
((U) p[6] << 8) | ((U) p[7] << 0));
}
forceinline constexpr void set_be16(byte *p, upx_uint16_t v) noexcept {
p[0] = (byte) ((v >> 8) & 0xff);
p[1] = (byte) ((v >> 0) & 0xff);
}
forceinline constexpr void set_be24(byte *p, upx_uint32_t v) noexcept {
p[0] = (byte) ((v >> 16) & 0xff);
p[1] = (byte) ((v >> 8) & 0xff);
p[2] = (byte) ((v >> 0) & 0xff);
}
forceinline constexpr void set_be32(byte *p, upx_uint32_t v) noexcept {
p[0] = (byte) ((v >> 24) & 0xff);
p[1] = (byte) ((v >> 16) & 0xff);
p[2] = (byte) ((v >> 8) & 0xff);
p[3] = (byte) ((v >> 0) & 0xff);
}
forceinline constexpr void set_be64(byte *p, upx_uint64_t v) noexcept {
p[0] = (byte) ((v >> 56) & 0xff);
p[1] = (byte) ((v >> 48) & 0xff);
p[2] = (byte) ((v >> 40) & 0xff);
p[3] = (byte) ((v >> 32) & 0xff);
p[4] = (byte) ((v >> 24) & 0xff);
p[5] = (byte) ((v >> 16) & 0xff);
p[6] = (byte) ((v >> 8) & 0xff);
p[7] = (byte) ((v >> 0) & 0xff);
}
forceinline constexpr upx_uint16_t get_le16(const byte *p) noexcept {
typedef unsigned U;
return (upx_uint16_t) (((U) p[0] << 0) | ((U) p[1] << 8));
}
forceinline constexpr upx_uint32_t get_le24(const byte *p) noexcept {
typedef upx_uint32_t U;
return (upx_uint32_t) (((U) p[0] << 0) | ((U) p[1] << 8) | ((U) p[2] << 16));
}
forceinline constexpr upx_uint32_t get_le32(const byte *p) noexcept {
typedef upx_uint32_t U;
return (upx_uint32_t) (((U) p[0] << 0) | ((U) p[1] << 8) | ((U) p[2] << 16) | ((U) p[3] << 24));
}
forceinline constexpr upx_uint64_t get_le64(const byte *p) noexcept {
typedef upx_uint64_t U;
return (upx_uint64_t) (((U) p[0] << 0) | ((U) p[1] << 8) | ((U) p[2] << 16) | ((U) p[3] << 24) |
((U) p[4] << 32) | ((U) p[5] << 40) | ((U) p[6] << 48) |
((U) p[7] << 56));
}
forceinline constexpr void set_le16(byte *p, upx_uint16_t v) noexcept {
p[0] = (byte) ((v >> 0) & 0xff);
p[1] = (byte) ((v >> 8) & 0xff);
}
forceinline constexpr void set_le24(byte *p, upx_uint32_t v) noexcept {
p[0] = (byte) ((v >> 0) & 0xff);
p[1] = (byte) ((v >> 8) & 0xff);
p[2] = (byte) ((v >> 16) & 0xff);
}
forceinline constexpr void set_le32(byte *p, upx_uint32_t v) noexcept {
p[0] = (byte) ((v >> 0) & 0xff);
p[1] = (byte) ((v >> 8) & 0xff);
p[2] = (byte) ((v >> 16) & 0xff);
p[3] = (byte) ((v >> 24) & 0xff);
}
forceinline constexpr void set_le64(byte *p, upx_uint64_t v) noexcept {
p[0] = (byte) ((v >> 0) & 0xff);
p[1] = (byte) ((v >> 8) & 0xff);
p[2] = (byte) ((v >> 16) & 0xff);
p[3] = (byte) ((v >> 24) & 0xff);
p[4] = (byte) ((v >> 32) & 0xff);
p[5] = (byte) ((v >> 40) & 0xff);
p[6] = (byte) ((v >> 48) & 0xff);
p[7] = (byte) ((v >> 56) & 0xff);
}
forceinline constexpr upx_uint16_t get_ne16(const byte *p) noexcept {
#if (ACC_ABI_BIG_ENDIAN)
return get_be16(p);
#else
return get_le16(p);
#endif
}
forceinline constexpr upx_uint32_t get_ne24(const byte *p) noexcept {
#if (ACC_ABI_BIG_ENDIAN)
return get_be24(p);
#else
return get_le24(p);
#endif
}
forceinline constexpr upx_uint32_t get_ne32(const byte *p) noexcept {
#if (ACC_ABI_BIG_ENDIAN)
return get_be32(p);
#else
return get_le32(p);
#endif
}
forceinline constexpr upx_uint64_t get_ne64(const byte *p) noexcept {
#if (ACC_ABI_BIG_ENDIAN)
return get_be64(p);
#else
return get_le64(p);
#endif
}
forceinline constexpr void set_ne16(byte *p, upx_uint16_t v) noexcept {
#if (ACC_ABI_BIG_ENDIAN)
set_be16(p, v);
#else
set_le16(p, v);
#endif
}
forceinline constexpr void set_ne24(byte *p, upx_uint32_t v) noexcept {
#if (ACC_ABI_BIG_ENDIAN)
set_be24(p, v);
#else
set_le24(p, v);
#endif
}
forceinline constexpr void set_ne32(byte *p, upx_uint32_t v) noexcept {
#if (ACC_ABI_BIG_ENDIAN)
set_be32(p, v);
#else
set_le32(p, v);
#endif
}
forceinline constexpr void set_ne64(byte *p, upx_uint64_t v) noexcept {
#if (ACC_ABI_BIG_ENDIAN)
set_be64(p, v);
#else
set_le64(p, v);
#endif
}
} // namespace compile_time
/*************************************************************************
// TriBool - tri-state bool
// an enum with an underlying type and 3 values

View File

@ -225,6 +225,7 @@ XSPAN_NAMESPACE_END
#ifndef XSPAN_DELETED_FUNCTION
#define XSPAN_DELETED_FUNCTION = delete
#endif
// function/method constraints
#define XSPAN_REQUIRES_CONVERTIBLE_ONE_DIRECTION(From, To, RType) \
typename std::enable_if<XSPAN_NS(XSpan_is_convertible) < From, To>::value, RType > ::type
@ -250,6 +251,7 @@ XSPAN_NAMESPACE_END
#include "xspan_impl_ptr_or_span.h"
#include "xspan_impl_span.h"
#include "xspan_impl_ptr.h"
#undef XSPAN_REQUIRES_CONVERTIBLE_ONE_DIRECTION
#undef XSPAN_REQUIRES_CONVERTIBLE_ANY_DIRECTION
#undef XSPAN_REQUIRES_CONVERTIBLE_A