Run the Unicorn semantics tests on Windows too - #1456
Conversation
The vcpkg workflow has failed on every run since 2026-06-27, on all three
platforms, for any PR that touches the tree:
CMake Error (install-absolute-destination) at src/libtriton/CMakeLists.txt:378 (install):
INSTALL command given absolute DESTINATION path:
/home/runner/work/Triton/Triton/out/install/linux-x64/lib/python3.11/site-packages
Nothing in the repository changed. .github/workflows/vcpkg.yml uses
lukka/get-cmake@latest, which is unpinned, so the runner moved from CMake 3.x
to 4.4.2; CMake 4 promoted install-absolute-destination into the developer
warning category, and CMakePresets.json sets "errors": { "dev": true }.
The prefix was redundant in the first place. In this branch PYTHON_SITE_PACKAGES
is already relative -- the execute_process just above it prints
"lib/pythonX.Y/site-packages" -- and install() resolves a relative DESTINATION
against CMAKE_INSTALL_PREFIX. Prefixing it again only made the path absolute.
Dropping the prefix keeps the destination byte-identical for a normal install
and additionally restores `cmake --install --prefix <other>`, which an absolute
DESTINATION silently ignores.
The other branch of the if() is left alone: it deliberately installs into the
interpreter's real site-packages when no prefix was given, so its absolute path
is intended. It is not reachable from the presets, which always set one.
Verified with CMake 4.4.2 locally: reproduced the error before the change, and
after it the generated cmake_install.cmake records
"${CMAKE_INSTALL_PREFIX}/lib/pythonX.Y/site-packages" -- the same location,
resolved relative to the prefix.
b029fed to
2ea8067
Compare
|
Heads-up on the red checks here: they are not caused by this PR. The failing job is The line number moves between runs only because commits above it shift it: #1457 fixes it, and this branch is now rebased on top of that so it can go green. Note that the workflow runs on these branches are currently held at |
…ndows
Immediate::Immediate(double, size, endianness) byte-swaps when the host and
the emulated platform disagree on byte order. The host side came from:
#ifdef LITTLE_ENDIAN // provided by CMake
CMake does provide it -- but only to one translation unit:
set_source_files_properties(utils/softfloat.cpp PROPERTIES COMPILE_DEFINITIONS
${CMAKE_CXX_BYTE_ORDER}
)
CMAKE_CXX_BYTE_ORDER expands to the literal LITTLE_ENDIAN or BIG_ENDIAN, so
utils/softfloat.cpp gets the macro and arch/immediate.cpp never does. What
immediate.cpp actually sees is the POSIX definition, and that does not mean
what the #ifdef assumes:
* On POSIX, <endian.h> defines LITTLE_ENDIAN and BIG_ENDIAN as named
constants (1234 and 4321), reaching this file transitively. The macro is
therefore always defined regardless of the actual byte order, so the test
is really "am I on POSIX". The correct spelling would have been
BYTE_ORDER == LITTLE_ENDIAN. It selects the right branch today only
because every platform this is built on happens to be little-endian.
* Under MSVC neither header nor per-source definition applies, the macro is
undefined, and Triton concludes it is running big-endian. Every AArch64
floating-point immediate is then byte-swapped on a little-endian machine:
fmov s0, #2.0 -> 0x00000040 (expected 0x40000000)
fmov s0, #1.0 -> 0x0000803f (expected 0x3f800000)
Extend the byte order to the whole library rather than one file, via the
existing triton/config.hpp, as TRITON_BIG_ENDIAN. The namespaced name also
avoids colliding with the POSIX LITTLE_ENDIAN/BIG_ENDIAN constants, which a
translation-unit-wide LITTLE_ENDIAN definition would risk.
Introduced in JonathanSalwan#1359.
These have been gated to Linux and Darwin since they were added, with the
comment "because the setup is easier". That is no longer true:
* unicorn (2.1.4) and lief (1.0.0) both publish win_amd64 wheels;
* none of the 27 unicorn_test*.py scripts nor the 12 lief-driven ARM32
crypto runners contain anything platform specific;
* .github/actions/install-triton-deps/windows already pip-installs both,
so Windows CI has been paying for the dependencies without using them.
Measured on windows-2022, with ubuntu-24.04 as a control on an identical
configuration (capstone 5.0.7, unicorn 2.1.4, lief 1.0.0): Windows 40/41,
Linux control 47/47. The counts differ because Windows does not register the
C++ example tests. The single Windows failure was UnicornAArch64Semantics on
"fmov s0, #2.0", which is the bug fixed by the preceding commit; with that
fix applied both platforms are green.
Cost is roughly ten minutes of Windows CI time. In exchange the AArch64,
ARM32, RISC-V and x86 semantics are cross-validated against a second emulator
on Windows, which the Python unit tests cannot do -- they check fixed expected
values, so they only catch what someone thought to write down.
2ea8067 to
8c30c97
Compare
…t fixes Brings in the three commits proposed upstream as JonathanSalwan#1457, JonathanSalwan#1455 and JonathanSalwan#1456: * absolute install DESTINATION that CMake >= 4 rejects * endianness detection that byte-swapped every AArch64 FP immediate on Windows builds * the platform gate that hid the differential test which found it
Summary
src/testers/CMakeLists.txthas gated the 39 semantics tests to Linux and Darwin since they were added, with the comment "because the setup is easier." That is no longer true, and the gate was concealing a real Windows-only correctness bug.Why the reason no longer holds
unicorn(2.1.4) andlief(1.0.0) both publishwin_amd64wheels.unicorn_test*.pyscripts or the 12 lief-driven ARM32 crypto runners contain anything platform specific. Searching all of them formmap,fcntl,subprocess,os.unameandplatform.systemmatches only the#!line, andctestinvokes them through${PYTHON_EXECUTABLE}rather than the shebang..github/actions/install-triton-deps/windowsalready runspython -m pip install unicorn lief, so Windows CI has been paying for the dependencies without using them.Measured
windows-2022as subject,ubuntu-24.04as control on an identical configuration — capstone 5.0.7, unicorn 2.1.4, lief 1.0.0,LLVM_INTERFACE=OFFon both, versions confirmed from the job logs:The totals differ because Windows does not register the C++ example tests and adds
DummyTest.38 of the 39 previously-gated tests pass on Windows unchanged. The single failure was:
which is the bug fixed by #1455. With it applied, both platforms are green.
Cost and benefit
Roughly ten minutes of Windows CI time. In exchange, the AArch64, ARM32, RISC-V and x86 semantics get cross-validated against a second emulator on Windows.
The Python unit tests cannot substitute for this. They check fixed expected values, so they only catch what someone thought to write down —
test_semantics.pyandtest_emulation.pypass on Windows today and never touchfmovwith an immediate. Differential testing against Unicorn is what found this, and it is the only thing in the tree that could have.