Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
201 changes: 201 additions & 0 deletions .github/workflows/CrossBuilds.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
name: Cross Build Tests
on:
push:
paths-ignore:
- ".gitignore"
- "docs/**"
- "ChangeLog"
- "CREDITS.TXT"
- "COMPILE_MAKE.TXT"
- "BUILDING.md"
- "CONTRIBUTING.md"
- "LICENSE.TXT"
- "LICENSE_LLVM.TXT"
- "README.md"
- "RELEASE_NOTES"
- "SPONSORS.TXT"
- "TODO"
pull_request:

# Stop previous runs on the same branch on new push
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
CI: true
UBSAN_OPTIONS: "halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1"
ASAN_OPTIONS: "halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1"
LSAN_OPTIONS: "halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1"

jobs:
Linux:
runs-on: ${{ matrix.config.os }}
name: ${{ matrix.config.name }}
strategy:
fail-fast: false
matrix:
config:
- {
name: 'QEMU Linux s390x',
os: ubuntu-24.04,
arch: x64,
build-system: 'cmake',
diet-build: 'OFF',
build_type: 'Debug',
diet_build: false,
packages: 'gcc-s390x-linux-gnu g++-s390x-linux-gnu binutils-s390x-linux-gnu libc6-dev-s390x-cross qemu-user-static',
cross_file: 'cross_configs/linux_s390x_ubuntu24.cmake',
}
- {
name: 'QEMU Linux Mips 32',
os: ubuntu-24.04,
arch: x64,
build-system: 'cmake',
diet-build: 'OFF',
build_type: 'Debug',
diet_build: false,
packages: 'gcc-mips-linux-gnu g++-mips-linux-gnu binutils-mips-linux-gnu libc6-dev-mips-cross qemu-user-static',
cross_file: 'cross_configs/linux_mips_ubuntu24.cmake',
}
- {
name: 'QEMU Linux Mips64el',
os: ubuntu-24.04,
arch: x64,
build-system: 'cmake',
diet-build: 'OFF',
build_type: 'Debug',
diet_build: false,
packages: 'gcc-mips64el-linux-gnuabi64 g++-mips64el-linux-gnuabi64 binutils-mips64el-linux-gnuabi64 libc6-dev-mips64el-cross qemu-user-static',
cross_file: 'cross_configs/linux_mips64_ubuntu24.cmake',
}
- {
name: 'QEMU Linux PPC64',
os: ubuntu-24.04,
arch: x64,
build-system: 'cmake',
diet-build: 'OFF',
build_type: 'Debug',
diet_build: false,
packages: 'gcc-powerpc64-linux-gnu g++-powerpc64-linux-gnu binutils-powerpc64-linux-gnu libc6-dev-ppc64-cross qemu-user-static',
cross_file: 'cross_configs/linux_ppc64_ubuntu24.cmake',
}
- {
name: 'QEMU Linux ARM',
os: ubuntu-24.04,
arch: x64,
build-system: 'cmake',
diet-build: 'OFF',
build_type: 'Debug',
diet_build: false,
packages: 'gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf binutils-arm-linux-gnueabihf libc6-dev-armhf-cross qemu-user-static',
cross_file: 'cross_configs/linux_arm_ubuntu24.cmake',
}
- {
name: '[BUILD ONLY] Windows i686 mingw',
os: ubuntu-24.04,
arch: x64,
build-system: 'cmake',
diet-build: 'OFF',
build_type: 'Debug',
diet_build: false,
skip_tests: true,
packages: 'gcc-mingw-w64-i686 g++-mingw-w64-i686 mingw-w64-tools',
cross_file: 'cross_configs/windows_i686_ubuntu24.cmake',
}
- {
name: '[BUILD ONLY] Android 35 (arm64_v8a) NDK 29',
os: ubuntu-24.04,
arch: x64,
build-system: 'cmake',
build_option: '-DANDROID_NDK=ndk/ -DANDROID_PLATFORM=android-35 -DANDROID_ABI=arm64-v8a',
diet-build: 'OFF',
build_type: 'Debug',
diet_build: false,
# QEMU alone can't emulate the binaries, because the NDK doesn't
# provide dynamic linker.
skip_tests: true,
packages: 'qemu-user-static',
ndk_version: 'r29',
cross_file: 'ndk/build/cmake/android.toolchain.cmake',
qemu: 'qemu-aarch64-static'
}

steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.config.python-version }}

- name: Install cross build dependencies
if: ${{ matrix.config.packages != '' }}
env:
packages: ${{ matrix.config.packages }}
run: |
sudo apt-get install -y ${packages}

- name: Setup Android NDK
if: contains(matrix.config.name, 'Android')
env:
ndk_version: ${{ matrix.config.ndk_version }}
qemu: ${{ matrix.config.qemu }}
cross_file: ${{ matrix.config.cross_file }}
run: |
wget -q https://dl.google.com/android/repository/android-ndk-${ndk_version}-linux.zip
mkdir ndk
unzip -q -d ndk android-ndk-${ndk_version}-linux.zip
mv ndk/*/* ndk/
cat ndk/source.properties

- name: cmake (cross build)
env:
build_option: ${{ matrix.config.build_option }}
build_type: ${{ matrix.config.build_type }}
cross_file: ${{ matrix.config.cross_file }}
run: |
cmake -DCMAKE_BUILD_TYPE=${build_type} \
-DCAPSTONE_BUILD_STATIC_LIBS=ON \
-S . \
-DCAPSTONE_BUILD_CSTEST=ON \
-DCAPSTONE_BUILD_DIET=${diet_build} \
-DCMAKE_TOOLCHAIN_FILE=${cross_file} \
${build_option} \
-B build .
cmake --build build --config ${build_type}

- name: unit tests
if: ${{ matrix.config.skip_tests != true }}
run: |
ctest --test-dir build --output-on-failure -R unit_*

- name: "Integration tests"
if: ${{ matrix.config.skip_tests != true }}
run: |
ctest --test-dir build --output-on-failure -R integration_c_*

- name: cstest MC
if: ${{ matrix.config.skip_tests != true }}
run: |
ctest --test-dir build --output-on-failure -R MCTests

- name: cstest details
if: ${{ matrix.config.skip_tests != true }}
run: |
ctest --test-dir build --output-on-failure -R DetailTests

- name: cstest issues
if: ${{ matrix.config.skip_tests != true }}
run: |
ctest --test-dir build --output-on-failure -R IssueTests

- name: cstest features
if: ${{ matrix.config.skip_tests != true }}
run: |
ctest --test-dir build --output-on-failure -R FeaturesTests

- name: Legacy integration tests
if: ${{ matrix.config.skip_tests != true }}
run: |
ctest --test-dir build --output-on-failure -R legacy*
6 changes: 3 additions & 3 deletions .github/workflows/build-wheels-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ jobs:
include:
# NOTE: Making this to parallelize and speed up workflow
# i686 - manylinux
# - { os: ubuntu-latest, arch: i686, cibw_build: 'cp*-manylinux*', cibw_skip: '' }
- { os: ubuntu-latest, arch: i686, cibw_build: 'cp*-manylinux*', cibw_skip: '' }
# i686 - musllinux
# - { os: ubuntu-latest, arch: i686, cibw_build: 'cp*-musllinux*', cibw_skip: '' }
- { os: ubuntu-latest, arch: i686, cibw_build: 'cp*-musllinux*', cibw_skip: '' }
# x86_64 - manylinux
- { os: ubuntu-latest, arch: x86_64, cibw_build: 'cp*-manylinux*', cibw_skip: '' }
# x86_64 - musllinux
Expand All @@ -63,7 +63,7 @@ jobs:
# windows - amd64
- { os: windows-latest, arch: AMD64, cibw_build: 'cp*', cibw_skip: '' }
# windows - x86
# - { os: windows-latest, arch: x86, cibw_build: 'cp*', cibw_skip: '' }
- { os: windows-latest, arch: x86, cibw_build: 'cp*', cibw_skip: '' }
# windows - arm64
- { os: windows-11-arm, arch: ARM64, cibw_build: 'cp*', cibw_skip: '*38* *39* *310*' }

Expand Down
37 changes: 36 additions & 1 deletion BUILDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,40 @@ By default, Capstone use system dynamic memory management, and both DIET and X86
modes are disabled. To use your own memory allocations, turn ON both DIET &
X86_REDUCE, run "cmake" with: `-DCAPSTONE_USE_SYS_DYN_MEM=0`, `-DCAPSTONE_BUILD_DIET=1`, `-DCAPSTONE_X86_REDUCE=1`

### Cross compilation

We have some example configurations for cross builds in [cross_configs](cross_configs/).
Build them with the following command (static build is of course optional):

```bash
cmake -DCMAKE_TOOLCHAIN_FILE=cross_configs/<cross_build_config>.cmake -DCAPSTONE_BUILD_STATIC_LIBS=ON -S . -B build
cmake --build build
```

See the cmake cross compilation [documentation](https://cmake.org/cmake/help/book/mastering-cmake/chapter/Cross%20Compiling%20With%20CMake.html)
for more details.

**Android**

The [Android SDK provides](https://developer.android.com/ndk/guides/cmake) a toolchain file for CMake.
It is the most reliable way to build Capstone for Android.

_Example:_

```bash
cmake -B build -DCMAKE_TOOLCHAIN_FILE=$NDK_PATH/build/cmake/android.toolchain.cmake -DANDROID_NDK=$NDK_PATH -DANDROID_ABI=arm64-v8a
cmake --build build
```

#### Test cross build with QEMU

Running the binaries with QEMU (here an example for s390x on Fedora 40)
is usually done with a command like this:

```bash
QEMU_LD_PREFIX=/usr/s390x-redhat-linux/sys-root/fc40/usr/ qemu-s390x-static ./build/cstool -d aarch64 01421bd501423bd5
```

### Developer specific options

- `CAPSTONE_DEBUG`: Change this to ON to enable extra debug assertions. Automatically enabled with `Debug` build.
Expand All @@ -106,8 +140,9 @@ X86_REDUCE, run "cmake" with: `-DCAPSTONE_USE_SYS_DYN_MEM=0`, `-DCAPSTONE_BUILD_
`cstest` is build together with Capstone by adding the flag `-DCAPSTONE_BUILD_CSTEST`.

The build requires `libyaml`. It is a fairly common package and should be provided by your package manager.
If not present it will attempt to build it from source.

_Note:_ Currently `cstest` us only supported on Linux.
_Note:_ Currently `cstest` is only tested on Linux.

If you run another operation system, please install `cstest_py`.
See `bindings/python/BUILDING.md` for instructions.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@ if(CAPSTONE_BUILD_STATIC_MSVC_RUNTIME)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif()

# The directory for external project patches.
set(EXTERNAL_PROJ_PATCH_DIR ${PROJECT_SOURCE_DIR}/ext_patches/)

## sources
set(SOURCES_ENGINE
cs.c
Expand Down
6 changes: 3 additions & 3 deletions CPackConfig.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
set(CPACK_DEBIAN_PACKAGE_MULTIARCH "same")

# Determine architecture for Debian package
if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")
if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64")
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i386" OR ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i686")
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "i386" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "i686")
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "i386")
elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm")
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "arm")
if(CMAKE_SIZE_OF_VOID_P EQUAL 4)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "armhf")
else()
Expand Down
6 changes: 3 additions & 3 deletions arch/AArch64/AArch64InstPrinter.c
Original file line number Diff line number Diff line change
Expand Up @@ -1131,7 +1131,7 @@ void printShifter(MCInst *MI, unsigned OpNum, SStream *O)
AArch64_AM_getShiftValue(Val) == 0)
return;
SStream_concat(
O, "%s%s%s%s#%d", ", ",
O, "%s%s%s%s#%u", ", ",
AArch64_AM_getShiftExtendName(AArch64_AM_getShiftType(Val)),
" ", markup("<imm:"), AArch64_AM_getShiftValue(Val));
SStream_concat0(O, markup(">"));
Expand Down Expand Up @@ -1202,7 +1202,7 @@ static void printMemExtendImpl(bool SignExtend, bool DoShift, unsigned Width,
if (getUseMarkup)
SStream_concat0(O, "<imm:");
unsigned ShiftAmount = DoShift ? Log2_32(Width / 8) : 0;
SStream_concat(O, "%s%d", "#", ShiftAmount);
SStream_concat(O, "%s%u", "#", ShiftAmount);
if (getUseMarkup)
SStream_concat0(O, ">");
}
Expand Down Expand Up @@ -2319,7 +2319,7 @@ void printSIMDType10Operand(MCInst *MI, unsigned OpNo, SStream *O)
unsigned Val = \
MCOperand_getImm(MCInst_getOperand(MI, (OpNo))); \
SStream_concat(O, "%s", markup("<imm:")); \
SStream_concat(O, "#%d", (Val * Angle) + Remainder); \
SStream_concat(O, "#%" PRId32, (int32_t)((Val * Angle) + Remainder)); \
SStream_concat0(O, markup(">")); \
}
DEFINE_printComplexRotationOp(180, 90);
Expand Down
17 changes: 10 additions & 7 deletions arch/ARM/ARMInstPrinter.c
Original file line number Diff line number Diff line change
Expand Up @@ -886,15 +886,17 @@ static inline void printNoHashImmediate(MCInst *MI, unsigned OpNum, SStream *O)
static inline void printPImmediate(MCInst *MI, unsigned OpNum, SStream *O)
{
add_cs_detail(MI, ARM_OP_GROUP_PImmediate, OpNum);
SStream_concat(O, "%s%d", "p",
MCOperand_getImm(MCInst_getOperand(MI, (OpNum))));
SStream_concat(
O, "%s%" PRIu32, "p",
(uint32_t)MCOperand_getImm(MCInst_getOperand(MI, (OpNum))));
}

static inline void printCImmediate(MCInst *MI, unsigned OpNum, SStream *O)
{
add_cs_detail(MI, ARM_OP_GROUP_CImmediate, OpNum);
SStream_concat(O, "%s%d", "c",
MCOperand_getImm(MCInst_getOperand(MI, (OpNum))));
SStream_concat(
O, "%s%" PRIu32, "c",
(uint32_t)MCOperand_getImm(MCInst_getOperand(MI, (OpNum))));
}

static inline void printCoprocOptionImm(MCInst *MI, unsigned OpNum, SStream *O)
Expand Down Expand Up @@ -1364,8 +1366,9 @@ static inline void printFBits16(MCInst *MI, unsigned OpNum, SStream *O)
{
add_cs_detail(MI, ARM_OP_GROUP_FBits16, OpNum);
SStream_concat(O, "%s%s", markup("<imm:"), "#");
SStream_concat(O, "%d",
16 - MCOperand_getImm(MCInst_getOperand(MI, (OpNum))));
SStream_concat(
O, "%" PRIu32,
(uint32_t)(16 - MCOperand_getImm(MCInst_getOperand(MI, (OpNum)))));
SStream_concat0(O, markup(">"));
}

Expand Down Expand Up @@ -1624,7 +1627,7 @@ DEFINE_printMVEVectorList(2) DEFINE_printMVEVectorList(4)
OpNo, Angle, Remainder); \
unsigned Val = \
MCOperand_getImm(MCInst_getOperand(MI, (OpNo))); \
SStream_concat(O, "#%d", (Val * Angle) + Remainder); \
SStream_concat(O, "#%u", (uint32_t)((Val * Angle) + Remainder)); \
}
DEFINE_printComplexRotationOp(90, 0) DEFINE_printComplexRotationOp(180,
90)
Expand Down
Loading
Loading