Modern Testing (#2456)

This commit is contained in:
Rot127 2024-08-31 13:33:38 +00:00 committed by GitHub
parent df72286749
commit 191db14531
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1754 changed files with 613736 additions and 22936 deletions

View File

@ -6,7 +6,7 @@ on:
- "docs/**"
- "ChangeLog"
- "CREDITS.TXT"
- "COMPILE.TXT"
- "COMPILE_MAKE.TXT"
- "COMPILE_MSVC.TXT"
- "COMPILE_CMAKE.TXT"
- "HACK.TXT"
@ -34,6 +34,7 @@ jobs:
os: ubuntu-22.04,
arch: x64,
build-system: 'make',
diet-build: 'OFF',
enable-asan: 'OFF'
}
- {
@ -41,34 +42,37 @@ jobs:
os: ubuntu-22.04,
arch: x64,
build-system: 'cmake',
diet-build: 'OFF',
enable-asan: 'OFF'
}
- {
name: 'ubuntu-22.04 x64 ASAN',
os: ubuntu-latest,
name: 'ubuntu-24.04 x64 ASAN',
os: ubuntu-24.04,
arch: x64,
build-system: 'cmake',
diet-build: 'OFF',
enable-asan: 'ON'
}
steps:
- uses: actions/checkout@v3
- name: prepare
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.config.python-version }}
- name: Prepare fuzzing
run: |
export LD_LIBRARY_PATH=`pwd`/tests/:$LD_LIBRARY_PATH
wget https://github.com/groundx/capstonefuzz/raw/master/corpus/corpus-libFuzzer-capstone_fuzz_disasmnext-latest.zip
unzip -q corpus-libFuzzer-capstone_fuzz_disasmnext-latest.zip -d suite/fuzz
git clone https://git.cryptomilk.org/projects/cmocka.git suite/cstest/cmocka
chmod +x suite/cstest/build_cstest.sh
- name: make
if: startsWith(matrix.config.build-system, 'make')
run: |
./make.sh
make check
sudo make install
cp libcapstone.so.5 libcapstone.so.5.0
- name: cmake
if: startsWith(matrix.config.build-system, 'cmake')
@ -82,47 +86,55 @@ jobs:
# build shared library
cmake -DCAPSTONE_INSTALL=1 -DBUILD_SHARED_LIBS=1 -DCMAKE_INSTALL_PREFIX=/usr -DCAPSTONE_BUILD_CSTEST=ON -DENABLE_ASAN=${asan} ..
sudo cmake --build . --config Release --target install
cp libcapstone.* ../
cp libcapstone.* ../tests/
cp test_* ../tests/
- name: Lower number of KASL randomized address bits
run: |
# Work-around ASAN bug https://github.com/google/sanitizers/issues/1716
sudo sysctl vm.mmap_rnd_bits=28
- name: "Compatibility header test build"
if: matrix.config.diet-build == 'OFF'
env:
asan: ${{ matrix.config.enable-asan }}
- name: "Compatibility header test"
if: startsWith(matrix.config.build-system, 'cmake') && matrix.config.diet-build == 'OFF'
run: |
cd "$(git rev-parse --show-toplevel)/suite/auto-sync/c_tests/"
if [ "$asan" = "ON" ]; then
clang -lcapstone -fsanitize=address src/test_arm64_compatibility_header.c -o test_arm64_compatibility_header
else
clang -lcapstone src/test_arm64_compatibility_header.c -o test_arm64_compatibility_header
fi
./test_arm64_compatibility_header
ctest --test-dir build --output-on-failure -R ASCompatibilityHeaderTest
- name: cstool - reaches disassembler engine
run: |
sh suite/run_invalid_cstool.sh
- name: cstest (cmake)
- name: cstest unit tests
if: startsWith(matrix.config.build-system, 'cmake')
run: |
python suite/cstest/cstest_report.py -D -d suite/MC
python suite/cstest/cstest_report.py -D -f suite/cstest/issues.cs
python suite/cstest/cstest_report.py -D -f tests/cs_details/issue.cs
ctest --test-dir build --output-on-failure -R UnitCSTest
- name: cstest (make)
if: startsWith(matrix.config.build-system, 'make')
- name: cstest integration tests
if: startsWith(matrix.config.build-system, 'cmake')
run: |
cd suite/cstest && ./build_cstest.sh
python cstest_report.py -D -t build/cstest -d ../MC
python cstest_report.py -D -t build/cstest -f issues.cs
python cstest_report.py -D -t build/cstest -f ../../tests/cs_details/issue.cs
cd ../../
ctest --test-dir build --output-on-failure -R IntegrationCSTest
- name: cstest MC
if: startsWith(matrix.config.build-system, 'cmake')
run: |
ctest --test-dir build --output-on-failure -R MCTests
- name: cstest details
if: startsWith(matrix.config.build-system, 'cmake')
run: |
ctest --test-dir build --output-on-failure -R DetailTests
- name: cstest issues
if: startsWith(matrix.config.build-system, 'cmake')
run: |
ctest --test-dir build --output-on-failure -R IssueTests
- name: cstest features
if: startsWith(matrix.config.build-system, 'cmake')
run: |
ctest --test-dir build --output-on-failure -R FeaturesTests
- name: Legacy integration tests
if: startsWith(matrix.config.build-system, 'cmake')
run: |
ctest --test-dir build --output-on-failure -R legacy*
Windows:
runs-on: ${{ matrix.config.os }}

View File

@ -3,11 +3,17 @@ on:
push:
paths:
- "suite/auto-sync/**"
- ".github/workflows/auto-sync.yml"
pull_request:
# Stop previous runs on the same branch on new push
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
check:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
defaults:
run:
working-directory: suite/auto-sync/
@ -30,9 +36,22 @@ jobs:
run: |
python3.11 -m black --check src/autosync
- name: Build llvm-tblgen
- name: Install llvm-mc
run: |
sudo apt install llvm-18
llvm-mc-18 --version
FileCheck-18 --version
sudo ln -s $(whereis -b llvm-mc-18 | grep -Eo "/.*") /usr/local/bin/llvm-mc
sudo ln -s $(whereis -b FileCheck-18 | grep -Eo "/.*") /usr/local/bin/FileCheck
llvm-mc --version
FileCheck --version
- name: Clone llvm-capstone
run: |
git clone https://github.com/capstone-engine/llvm-capstone.git vendor/llvm_root
- name: Build llvm-tblgen
run: |
cd vendor/llvm_root
mkdir build
cd build
@ -40,6 +59,17 @@ jobs:
cmake --build . --target llvm-tblgen --config Debug
cd ../../../
- name: Test Header patcher
run: |
python -m unittest src/autosync/Tests/test_header_patcher.py
python -m unittest src/autosync/Tests/test_mcupdater.py
- name: Remove llvm-mc
run: |
sudo apt remove llvm-18
sudo rm /usr/local/bin/llvm-mc
sudo rm /usr/local/bin/FileCheck
- name: Test generation of inc files
run: |
./src/autosync/ASUpdater.py -d -a AArch64 -s IncGen
@ -63,11 +93,9 @@ jobs:
./src/autosync/ASUpdater.py --ci -d -a PPC -s Translate
./src/autosync/ASUpdater.py --ci -d -a LoongArch -s Translate
- name: Test Header patcher
run: |
python -m unittest src/autosync/Tests/test_header_patcher.py
python -m unittest src/autosync/Tests/test_mcupdater.py
- name: Differ - Test save file is up-to-date
run: |
./src/autosync/cpptranslator/Differ.py -a AArch64 --check_saved
./src/autosync/cpptranslator/Differ.py -a ARM --check_saved
./src/autosync/cpptranslator/Differ.py -a PPC --check_saved
./src/autosync/cpptranslator/Differ.py -a LoongArch --check_saved

View File

@ -8,11 +8,11 @@ on:
jobs:
analyze:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
name: clang-tidy
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install clang-tidy
@ -26,9 +26,9 @@ jobs:
CC=clang sudo cmake --build . --config Release
cd ..
- name: Install clang-tidy-15
- name: Install clang-tidy-18
run: |
sudo apt install clang-tidy-15
sudo apt install clang-tidy-18
- name: Check for warnings
env:
@ -36,3 +36,8 @@ jobs:
head_sha: ${{ github.event.pull_request.head.sha }}
run: |
./run-clang-tidy.sh build
- uses: actions/upload-artifact@v4
if: ${{ failure() }}
with:
path: ct-warnings.txt

View File

@ -28,5 +28,30 @@ jobs:
- name: Build and install capstone
run: pip install ./bindings/python
- name: Run tests
- name: Install cstest_py
run: pip install ./bindings/python/cstest_py
- name: Run legacy tests
run: python ./bindings/python/tests/test_all.py
- name: cstest_py integration tests
run: |
cd suite/cstest/test/
python3 ./integration_tests.py cstest_py
cd ../../../
- name: cstest_py MC
run: |
cstest_py tests/MC/
- name: cstest_py details
run: |
cstest_py tests/details/
- name: cstest_py issues
run: |
cstest_py tests/issues/
- name: cstest_py features
run: |
cstest_py tests/features/

5
.gitignore vendored
View File

@ -25,6 +25,7 @@
# python
bindings/python/build/
bindings/python/capstone.egg-info/
bindings/python/cstest_py/src/cstest_py.egg**
bindings/cython/capstone.egg-info/
*.pyc
@ -133,7 +134,6 @@ fuzz_disasm
fuzz_decode_platform
capstone_get_setup
suite/fuzz/corpus
suite/cstest/cmocka/
*.s
@ -147,3 +147,6 @@ android-ndk-*
# Auto-sync files
suite/auto-sync/src/autosync.egg-info
# clangd cache
/.cache

View File

@ -60,7 +60,7 @@ option(BUILD_SHARED_LIBS "Build shared library" OFF)
option(CAPSTONE_BUILD_STATIC_RUNTIME "Embed static runtime" ${BUILD_SHARED_LIBS})
option(CAPSTONE_BUILD_MACOS_THIN "Disable universal2 builds on macOS" OFF)
option(CAPSTONE_BUILD_DIET "Build diet library" OFF)
option(CAPSTONE_BUILD_TESTS "Build tests" ${PROJECT_IS_TOP_LEVEL})
option(CAPSTONE_BUILD_LEGACY_TESTS "Build legacy tests" ${PROJECT_IS_TOP_LEVEL})
option(CAPSTONE_BUILD_CSTOOL "Build cstool" ${PROJECT_IS_TOP_LEVEL})
option(CAPSTONE_BUILD_CSTEST "Build cstest" OFF)
option(CAPSTONE_USE_DEFAULT_ALLOC "Use default memory allocation functions" ON)
@ -69,13 +69,21 @@ option(CAPSTONE_ARCHITECTURE_DEFAULT "Whether architectures are enabled by defau
option(CAPSTONE_DEBUG "Whether to enable extra debug assertions" OFF)
option(CAPSTONE_INSTALL "Generate install target" ${PROJECT_IS_TOP_LEVEL})
option(ENABLE_ASAN "Enable address sanitizer" OFF)
option(ENABLE_COVERAGE "Enable test coverage" OFF)
if (ENABLE_ASAN)
message("Enabling ASAN")
add_definitions(-DASAN_ENABLED)
add_compile_options(-fsanitize=address)
add_link_options(-fsanitize=address)
endif()
if (ENABLE_COVERAGE)
message("Enabling COVERAGE")
add_compile_options(--coverage)
add_link_options(--coverage)
endif()
# If building for OSX it's best to allow CMake to handle building both architectures
if(APPLE AND NOT CAPSTONE_BUILD_MACOS_THIN)
set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64")
@ -208,8 +216,6 @@ set(HEADERS_COMMON
include/capstone/loongarch.h
)
set(TEST_SOURCES test_basic.c test_detail.c test_skipdata.c test_iter.c)
## architecture support
if(CAPSTONE_ARM_SUPPORT)
add_definitions(-DCAPSTONE_HAS_ARM)
@ -239,7 +245,6 @@ if(CAPSTONE_ARM_SUPPORT)
arch/ARM/ARMGenCSMappingInsnName.inc
arch/ARM/ARMGenSystemRegister.inc
)
set(TEST_SOURCES ${TEST_SOURCES} test_arm.c)
endif()
if(CAPSTONE_AARCH64_SUPPORT)
@ -270,7 +275,6 @@ if(CAPSTONE_AARCH64_SUPPORT)
arch/AArch64/AArch64GenCSMappingInsnName.inc
arch/AArch64/AArch64GenCSMappingInsnOp.inc
)
set(TEST_SOURCES ${TEST_SOURCES} test_aarch64.c)
endif()
if(CAPSTONE_MIPS_SUPPORT)
@ -302,7 +306,6 @@ if(CAPSTONE_MIPS_SUPPORT)
arch/Mips/MipsInstPrinter.h
arch/Mips/MipsMapping.h
)
set(TEST_SOURCES ${TEST_SOURCES} test_mips.c)
endif()
if(CAPSTONE_PPC_SUPPORT)
@ -332,7 +335,6 @@ if(CAPSTONE_PPC_SUPPORT)
arch/PowerPC/PPCGenSubtargetInfo.inc
arch/PowerPC/PPCGenRegisterInfo.inc
)
set(TEST_SOURCES ${TEST_SOURCES} test_ppc.c)
endif()
if(CAPSTONE_X86_SUPPORT)
@ -386,7 +388,6 @@ if(CAPSTONE_X86_SUPPORT)
if(NOT CAPSTONE_BUILD_DIET)
set(SOURCES_X86 ${SOURCES_X86} arch/X86/X86ATTInstPrinter.c)
endif()
set(TEST_SOURCES ${TEST_SOURCES} test_x86.c test_customized_mnem.c)
endif()
if(CAPSTONE_SPARC_SUPPORT)
@ -409,7 +410,6 @@ if(CAPSTONE_SPARC_SUPPORT)
arch/Sparc/SparcMapping.h
arch/Sparc/SparcMappingInsn.inc
)
set(TEST_SOURCES ${TEST_SOURCES} test_sparc.c)
endif()
if(CAPSTONE_SYSZ_SUPPORT)
@ -434,7 +434,6 @@ if(CAPSTONE_SYSZ_SUPPORT)
arch/SystemZ/SystemZMappingInsn.inc
arch/SystemZ/SystemZMCTargetDesc.h
)
set(TEST_SOURCES ${TEST_SOURCES} test_systemz.c)
endif()
if(CAPSTONE_XCORE_SUPPORT)
@ -455,7 +454,6 @@ if(CAPSTONE_XCORE_SUPPORT)
arch/XCore/XCoreMapping.h
arch/XCore/XCoreMappingInsn.inc
)
set(TEST_SOURCES ${TEST_SOURCES} test_xcore.c)
endif()
if(CAPSTONE_M68K_SUPPORT)
@ -468,7 +466,6 @@ if(CAPSTONE_M68K_SUPPORT)
set(HEADERS_M68K
arch/M68K/M68KDisassembler.h
)
set(TEST_SOURCES ${TEST_SOURCES} test_m68k.c)
endif()
if(CAPSTONE_TMS320C64X_SUPPORT)
@ -488,7 +485,6 @@ if(CAPSTONE_TMS320C64X_SUPPORT)
arch/TMS320C64x/TMS320C64xInstPrinter.h
arch/TMS320C64x/TMS320C64xMapping.h
)
set(TEST_SOURCES ${TEST_SOURCES} test_tms320c64x.c)
endif()
if(CAPSTONE_M680X_SUPPORT)
@ -503,7 +499,6 @@ if(CAPSTONE_M680X_SUPPORT)
arch/M680X/M680XDisassembler.h
arch/M680X/M680XDisassemblerInternals.h
)
set(TEST_SOURCES ${TEST_SOURCES} test_m680x.c)
endif()
if(CAPSTONE_EVM_SUPPORT)
@ -520,7 +515,6 @@ if(CAPSTONE_EVM_SUPPORT)
arch/EVM/EVMMapping.h
arch/EVM/EVMMappingInsn.inc
)
set(TEST_SOURCES ${TEST_SOURCES} test_evm.c)
endif()
if(CAPSTONE_WASM_SUPPORT)
@ -536,7 +530,6 @@ if(CAPSTONE_WASM_SUPPORT)
arch/WASM/WASMInstPrinter.h
arch/WASM/WASMMapping.h
)
set(TEST_SOURCES ${TEST_SOURCES} test_wasm.c)
endif()
if(CAPSTONE_MOS65XX_SUPPORT)
@ -547,7 +540,6 @@ if(CAPSTONE_MOS65XX_SUPPORT)
set(HEADERS_SOURCES_MOS65XX
arch/MOS65XX/MOS65XXDisassembler.h
)
set(TEST_SOURCES ${TEST_SOURCES} test_mos65xx.c)
endif()
if(CAPSTONE_BPF_SUPPORT)
@ -565,7 +557,6 @@ if(CAPSTONE_BPF_SUPPORT)
arch/BPF/BPFMapping.h
arch/BPF/BPFModule.h
)
set(TEST_SOURCES ${TEST_SOURCES} test_bpf.c)
endif()
if(CAPSTONE_RISCV_SUPPORT)
@ -591,7 +582,6 @@ if(CAPSTONE_RISCV_SUPPORT)
arch/RISCV/RISCVMappingInsn.inc
arch/RISCV/RISCVMappingInsnOp.inc
)
set(TEST_SOURCES ${TEST_SOURCES} test_riscv.c)
endif()
if(CAPSTONE_SH_SUPPORT)
@ -607,7 +597,6 @@ if(CAPSTONE_SH_SUPPORT)
arch/SH/SHModule.h
arch/SH/SHInsnTable.inc
)
set(TEST_SOURCES ${TEST_SOURCES} test_sh.c)
endif()
if (CAPSTONE_TRICORE_SUPPORT)
@ -628,7 +617,6 @@ if (CAPSTONE_TRICORE_SUPPORT)
arch/TriCore/TriCoreMapping.h
arch/TriCore/TriCoreModule.h
)
set(TEST_SOURCES ${TEST_SOURCES} test_tricore.c)
endif ()
if (CAPSTONE_ALPHA_SUPPORT)
@ -652,7 +640,6 @@ if (CAPSTONE_ALPHA_SUPPORT)
arch/Alpha/AlphaGenCSMappingInsn.inc
arch/Alpha/AlphaGenCSMappingInsnName.inc
)
set(TEST_SOURCES ${TEST_SOURCES} test_alpha.c)
endif ()
if(CAPSTONE_HPPA_SUPPORT)
@ -670,7 +657,6 @@ if(CAPSTONE_HPPA_SUPPORT)
arch/HPPA/HPPAMapping.h
arch/HPPA/HPPAModule.h
)
set(TEST_SOURCES ${TEST_SOURCES} test_hppa.c)
endif()
if (CAPSTONE_LOONGARCH_SUPPORT)
@ -688,7 +674,6 @@ if (CAPSTONE_LOONGARCH_SUPPORT)
arch/LoongArch/LoongArchModule.h
arch/LoongArch/LoongArchLinkage.h
)
set(TEST_SOURCES ${TEST_SOURCES} test_loongarch.c)
endif ()
if (CAPSTONE_OSXKERNEL_SUPPORT)
@ -766,27 +751,13 @@ if(BUILD_SHARED_LIBS)
)
endif()
if(CAPSTONE_BUILD_TESTS)
set(CMAKE_FOLDER "Tests")
enable_testing()
foreach(TSRC ${TEST_SOURCES})
string(REGEX REPLACE ".c$" "" TBIN ${TSRC})
add_executable(${TBIN} "tests/${TSRC}")
target_link_libraries(${TBIN} PRIVATE capstone)
add_test(NAME "capstone_${TBIN}" COMMAND ${TBIN})
endforeach()
if(CAPSTONE_ARM_SUPPORT)
set(ARM_REGRESS_TEST test_arm_regression.c)
string(REGEX REPLACE ".c$" "" ARM_REGRESS_BIN ${ARM_REGRESS_TEST})
add_executable(${ARM_REGRESS_BIN} "suite/arm/${ARM_REGRESS_TEST}")
target_link_libraries(${ARM_REGRESS_BIN} PRIVATE capstone)
add_test(NAME "capstone_${ARM_REGRESS_BIN}" COMMAND ${ARM_REGRESS_BIN})
endif()
# fuzz target built with the tests
add_executable(fuzz_disasm suite/fuzz/onefile.c suite/fuzz/fuzz_disasm.c suite/fuzz/platform.c)
target_link_libraries(fuzz_disasm PRIVATE capstone)
unset(CMAKE_FOLDER)
endif()
# Fuzzer if this is moved to it's own CMakeLists.txt (as it should be)
# the OSS fuzzer build fails. And must be fixed.
# Simply because it builds the fuzzer there again with hard-coded paths.
# See: https://github.com/google/oss-fuzz/blob/master/projects/capstone/build.sh
# and: https://github.com/capstone-engine/capstone/issues/2454
add_executable(fuzz_disasm ${PROJECT_SOURCE_DIR}/suite/fuzz/onefile.c ${PROJECT_SOURCE_DIR}/suite/fuzz/fuzz_disasm.c ${PROJECT_SOURCE_DIR}/suite/fuzz/platform.c)
target_link_libraries(fuzz_disasm PRIVATE capstone)
source_group("Source\\Engine" FILES ${SOURCES_ENGINE})
source_group("Source\\ARM" FILES ${SOURCES_ARM})
@ -900,7 +871,6 @@ if(CAPSTONE_INSTALL)
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY
)
set(CMAKE_FOLDER)
add_custom_target(UNINSTALL COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
set_target_properties(UNINSTALL PROPERTIES
FOLDER CMakePredefinedTargets
@ -919,32 +889,17 @@ if(CAPSTONE_BUILD_CSTOOL)
endif()
if(CAPSTONE_BUILD_CSTEST)
include(ExternalProject)
ExternalProject_Add(cmocka_ext
PREFIX extern
GIT_REPOSITORY "https://git.cryptomilk.org/projects/cmocka.git"
GIT_TAG "origin/stable-1.1"
GIT_SHALLOW true
CONFIGURE_COMMAND cmake -DBUILD_SHARED_LIBS=OFF ../cmocka_ext/
BUILD_COMMAND cmake --build . --config Release
INSTALL_COMMAND ""
)
set(CMOCKA_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/extern/src/cmocka_ext/include)
set(CMOCKA_LIB_DIR ${CMAKE_CURRENT_BINARY_DIR}/extern/src/cmocka_ext-build/src/)
add_library(cmocka STATIC IMPORTED)
set_target_properties(cmocka PROPERTIES IMPORTED_LOCATION ${CMOCKA_LIB_DIR}/libcmocka.a)
enable_testing()
set(CSTEST_DIR ${PROJECT_SOURCE_DIR}/suite/cstest)
add_subdirectory(${CSTEST_DIR})
file(GLOB CSTEST_SRC suite/cstest/src/*.c)
add_executable(cstest ${CSTEST_SRC})
add_dependencies(cstest cmocka_ext)
target_link_libraries(cstest PUBLIC capstone cmocka)
target_include_directories(cstest PRIVATE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
${PROJECT_SOURCE_DIR}/suite/cstest/include
${CMOCKA_INCLUDE_DIR}
)
# Integration and unit tests
set(TESTS_INTEGRATION_DIR ${PROJECT_SOURCE_DIR}/tests/integration)
add_subdirectory(${TESTS_INTEGRATION_DIR})
set(TESTS_UNIT_DIR ${PROJECT_SOURCE_DIR}/tests/unit)
add_subdirectory(${TESTS_UNIT_DIR})
if(CAPSTONE_INSTALL)
install(TARGETS cstest EXPORT capstone-targets DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
# Unit tests for auto-sync
set(AUTO_SYNC_C_TEST_DIR ${PROJECT_SOURCE_DIR}/suite/auto-sync/c_tests/)
add_subdirectory(${AUTO_SYNC_C_TEST_DIR})
endif()

View File

@ -1,8 +1,6 @@
This documentation explains how to compile Capstone with CMake, focus on
using Microsoft Visual C as the compiler.
To compile Capstone on *nix, see COMPILE.TXT.
To compile Capstone on Windows using Visual Studio, see COMPILE_MSVC.TXT.
*-*-*-*-*-*
@ -57,7 +55,7 @@ Get CMake for free from http://www.cmake.org.
- CAPSTONE_X86_REDUCE: change this to ON to make X86 binary smaller.
- CAPSTONE_X86_ATT_DISABLE: change this to ON to disable AT&T syntax on x86.
- CAPSTONE_DEBUG: change this to ON to enable extra debug assertions.
- CAPSTONE_BUILD_CSTEST: Build `cstest` in `suite/cstest/`
- CAPSTONE_BUILD_CSTEST: Build `cstest` in `suite/cstest/`. `cstest` requires `libyaml` on your system.
- ENABLE_ASAN: Compiles Capstone with the address sanitizer.
By default, Capstone use system dynamic memory management, and both DIET and X86_REDUCE

View File

@ -1,3 +1,11 @@
# NOTICE
> Please be aware that the Makefile build is deprecated.
> Use cmake instead.
<hr>
This documentation explains how to compile, install & run Capstone on MacOSX,
Linux, *BSD & Solaris. We also show steps to cross-compile for Microsoft Windows.

View File

@ -1,7 +1,7 @@
This documentation explains how to compile Capstone on Windows using
Microsoft Visual Studio version 2010 or newer.
To compile Capstone on *nix, see COMPILE.TXT
To compile Capstone on *nix, see COMPILE_CMAKE.TXT
To compile Capstone with CMake, see COMPILE_CMAKE.TXT

View File

@ -3,7 +3,7 @@ Code structure
Capstone source is organized as followings.
. <- core engine + README + COMPILE.TXT etc
. <- core engine + README + COMPILE_CMAKE.TXT etc
├── arch <- code handling disasm engine for each arch
│   ├── AArch64 <- AArch64 engine
│   ├── Alpha <- Alpha engine
@ -39,7 +39,7 @@ Capstone source is organized as followings.
└── xcode <- Xcode support (for MacOSX compile)
Follow the instructions in COMPILE.TXT for how to compile and run test code.
Follow the instructions in COMPILE_CMAKE.TXT for how to compile and run test code.
Note: if you find some strange bugs, it is recommended to firstly clean
the code and try to recompile/reinstall again. This can be done with:
@ -111,13 +111,13 @@ Compile:
Tests:
- tests/Makefile
- tests/test_basic.c
- tests/test_detail.c
- tests/test_iter.c
- tests/test_newarch.c
- suite/fuzz/platform.c: add the architecture and its modes to the list of fuzzed platforms
- suite/capstone_get_setup.c
- suite/MC/newarch/mode.mc: samples
- suite/test_corpus.py: correspondence between architecture and mode as text and architecture number for fuzzing
- suite/cstest/
Bindings:
- bindings/Makefile

View File

@ -457,12 +457,6 @@ PKGCFGF = $(BLDIR)/$(LIBNAME).pc
all: $(LIBRARY) $(ARCHIVE) $(PKGCFGF)
ifeq (,$(findstring yes,$(CAPSTONE_BUILD_CORE_ONLY)))
@V=$(V) CC=$(CC) $(MAKE) -C cstool
ifndef BUILDDIR
$(MAKE) -C tests
else
$(MAKE) -C tests BUILDDIR=$(BLDIR)
endif
$(call install-library,$(BLDIR)/tests/)
endif
ifeq ($(CAPSTONE_SHARED),yes)
@ -556,9 +550,7 @@ clean:
ifeq (,$(findstring yes,$(CAPSTONE_BUILD_CORE_ONLY)))
$(MAKE) -C cstool clean
$(MAKE) -C tests clean
$(MAKE) -C suite/fuzz clean
rm -f $(BLDIR)/tests/lib$(LIBNAME).$(EXT)
endif
ifdef BUILDDIR
@ -583,23 +575,8 @@ dist:
git archive --format=tar.gz --prefix=capstone-$(DIST_VERSION)/ $(TAG) > capstone-$(DIST_VERSION).tgz
git archive --format=zip --prefix=capstone-$(DIST_VERSION)/ $(TAG) > capstone-$(DIST_VERSION).zip
TESTS = test_basic test_detail test_arm test_aarch64 test_m68k test_mips test_ppc test_sparc test_tricore test_hppa
TESTS += test_systemz test_x86 test_xcore test_iter test_evm test_riscv test_mos65xx test_wasm test_bpf test_alpha
TESTS += test_loongarch
TESTS += test_basic.static test_detail.static test_arm.static test_aarch64.static
TESTS += test_m68k.static test_mips.static test_ppc.static test_sparc.static
TESTS += test_systemz.static test_x86.static test_xcore.static test_m680x.static
TESTS += test_skipdata test_skipdata.static test_iter.static test_evm.static test_riscv.static
TESTS += test_mos65xx.static test_wasm.static test_bpf.static test_alpha.static test_hppa.static
TESTS += test_loongarch.static
check: $(TESTS)
checkfuzz: fuzztest fuzzallcorp
test_%:
./tests/$@ > /dev/null && echo OK || echo FAILED
FUZZ_INPUTS = $(shell find suite/MC -type f -name '*.cs')
buildfuzz:

View File

@ -400,3 +400,44 @@ void map_set_alias_id(MCInst *MI, const SStream *O, const name_map *alias_mnem_i
MI->flat_insn->alias_id = name2id(alias_mnem_id_map, map_size, alias_mnem);
}
/// Does a binary search over the given map and searches for @id.
/// If @id exists in @map, it sets @found to true and returns
/// the value for the @id.
/// Otherwise, @found is set to false and it returns UINT64_MAX.
///
/// Of course it assumes the map is sorted.
uint64_t enum_map_bin_search(const cs_enum_id_map *map, size_t map_len,
const char *id, bool *found)
{
size_t l = 0;
size_t r = map_len;
size_t id_len = strlen(id);
while (l <= r) {
size_t m = (l + r) / 2;
size_t j = 0;
size_t i = 0;
size_t entry_len = strlen(map[m].str);
while (j < entry_len && i < id_len && id[i] == map[m].str[j]) {
++j, ++i;
}
if (i == id_len && j == entry_len) {
*found = true;
return map[m].val;
}
if (id[i] < map[m].str[j]) {
r = m - 1;
} else if (id[i] > map[m].str[j]) {
l = m + 1;
}
if (m == 0 || (l + r) / 2 >= map_len) {
// Break before we go out of bounds.
break;
}
}
*found = false;
return UINT64_MAX;
}

View File

@ -232,4 +232,27 @@ bool map_use_alias_details(const MCInst *MI);
void map_set_alias_id(MCInst *MI, const SStream *O, const name_map *alias_mnem_id_map, int map_size);
/// Mapping from Capstone enumeration identifiers and their values.
///
/// This map MUST BE sorted to allow binary searches.
/// Please always ensure the map is sorted after you added a value.
///
/// You can sort the map with Python.
/// Copy the map into a file and run:
///
/// ```python
/// with open("/tmp/file_with_map_entries") as f:
/// text = f.readlines()
///
/// text.sort()
/// print(''.join(text))
/// ```
typedef struct {
const char *str; ///< The name of the enumeration identifier
uint64_t val; ///< The value of the identifier
} cs_enum_id_map;
uint64_t enum_map_bin_search(const cs_enum_id_map *map, size_t map_len,
const char *id, bool *found);
#endif // CS_MAPPING_H

View File

@ -49,7 +49,7 @@ Further information is available at https://www.capstone-engine.org
Compile
-------
See COMPILE.TXT file for how to compile and install Capstone.
See [COMPILE_CMAKE.TXT](COMPILE_CMAKE.TXT) file for how to compile and install Capstone.
Documentation

View File

@ -35510,6 +35510,7 @@ static DecodeStatus fname(const uint8_t DecodeTable[], MCInst *MI, \
/* Decoding complete. */ \
return S; \
} else { \
MCInst_clear(MI); \
/* If the decoding was incomplete, skip. */ \
Ptr += NumToSkip; \
/* Reset decode status. This also drops a SoftFail status that could be */ \

View File

@ -462,12 +462,18 @@ void printInst(MCInst *MI, uint64_t Address, const char *Annot, SStream *O)
if ((Opcode == AArch64_MOVZXi || Opcode == AArch64_MOVZWi ||
Opcode == AArch64_MOVNXi || Opcode == AArch64_MOVNWi) &&
MCOperand_isExpr(MCInst_getOperand(MI, (1)))) {
SStream_concat0(O, "<llvm-expr>");
printUInt64Bang(O, MCInst_getOpVal(MI, 1));
if (detail_is_set(MI) && useAliasDetails) {
AArch64_set_detail_op_imm(MI, 1, AARCH64_OP_IMM, MCInst_getOpVal(MI, 1));
}
}
if ((Opcode == AArch64_MOVKXi || Opcode == AArch64_MOVKWi) &&
MCOperand_isExpr(MCInst_getOperand(MI, (2)))) {
SStream_concat0(O, "<llvm-expr>");
printUInt64Bang(O, MCInst_getOpVal(MI, 2));
if (detail_is_set(MI) && useAliasDetails) {
AArch64_set_detail_op_imm(MI, 2, AARCH64_OP_IMM, MCInst_getOpVal(MI, 2));
}
}
// MOVZ, MOVN and "ORR wzr, #imm" instructions are aliases for MOV, but
@ -994,7 +1000,7 @@ void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
printInt64Bang(O, MCOperand_getImm(Op));
SStream_concat0(O, markup(">"));
} else {
SStream_concat0(O, "<llvm-expr>");
printUInt64Bang(O, MCInst_getOpVal(MI, OpNo));
}
}
@ -1282,7 +1288,7 @@ DEFINE_printRegWithShiftExtend(false, 128, x, 0);
assert(0 && \
"Unsupported predicate-as-counter register"); \
SStream_concat(O, "%s", "pn"); \
printUInt32(O, (Reg - AArch64_P0)); \
printUInt32(O, (Reg - AArch64_PN0)); \
switch (EltSize) { \
case 0: \
break; \
@ -1380,7 +1386,7 @@ void printUImm12Offset(MCInst *MI, unsigned OpNum, unsigned Scale, SStream *O)
printUInt32Bang(O, (MCOperand_getImm(MO) * Scale));
SStream_concat0(O, markup(">"));
} else {
SStream_concat0(O, "<llvm-expr>");
printUInt64Bang(O, MCOperand_getImm(MO));
}
}
@ -1395,7 +1401,7 @@ void printAMIndexedWB(MCInst *MI, unsigned OpNum, unsigned Scale, SStream *O)
printUInt32Bang(O, MCOperand_getImm(MO1) * Scale);
SStream_concat0(O, markup(">"));
} else {
SStream_concat0(O, "<llvm-expr>");
printUInt64Bang(O, MCOperand_getImm(MO1));
}
SStream_concat0(O, "]");
}
@ -1964,7 +1970,7 @@ void printImplicitlyTypedVectorList(MCInst *MI, unsigned OpNum, SStream *O)
NumLanes), \
LaneKind), \
OpNum, NumLanes, CHAR(LaneKind)); \
if (CHAR(LaneKind) == 0) { \
if (CHAR(LaneKind) == '0') { \
printVectorList(MI, OpNum, O, ""); \
return; \
} \
@ -2026,7 +2032,7 @@ void printAlignedLabel(MCInst *MI, uint64_t Address, unsigned OpNum, SStream *O)
return;
}
SStream_concat0(O, "<llvm-expr>");
printUInt64Bang(O, MCOperand_getImm(Op));
}
void printAdrLabel(MCInst *MI, uint64_t Address, unsigned OpNum, SStream *O)
@ -2048,7 +2054,7 @@ void printAdrLabel(MCInst *MI, uint64_t Address, unsigned OpNum, SStream *O)
return;
}
SStream_concat0(O, "<llvm-expr>");
printUInt64Bang(O, MCOperand_getImm(Op));
}
void printAdrpLabel(MCInst *MI, uint64_t Address, unsigned OpNum, SStream *O)
@ -2070,7 +2076,7 @@ void printAdrpLabel(MCInst *MI, uint64_t Address, unsigned OpNum, SStream *O)
return;
}
SStream_concat0(O, "<llvm-expr>");
printUInt64Bang(O, MCOperand_getImm(Op));
}
void printAdrAdrpLabel(MCInst *MI, uint64_t Address, unsigned OpNum, SStream *O) {
@ -2095,7 +2101,7 @@ void printAdrAdrpLabel(MCInst *MI, uint64_t Address, unsigned OpNum, SStream *O)
return;
}
SStream_concat0(O, "<llvm-expr>");
printUInt64Bang(O, MCOperand_getImm(Op));
}
void printBarrierOption(MCInst *MI, unsigned OpNo, SStream *O)
@ -2287,6 +2293,8 @@ void printSVEPattern(MCInst *MI, unsigned OpNum, SStream *O)
AArch64SVEPredPattern_lookupSVEPREDPATByEncoding(Val);
if (Pat)
SStream_concat0(O, Pat->Name);
else
printUInt32Bang(O, Val);
}
void printSVEVecLenSpecifier(MCInst *MI, unsigned OpNum, SStream *O)
@ -2371,7 +2379,7 @@ DECLARE_printImmSVE_U64(uint64_t);
#define DEFINE_isSignedType(T) \
static inline bool CONCAT(isSignedType, T)() \
{ \
return CHAR(t) == 'i'; \
return CHAR(T) == 'i'; \
}
DEFINE_isSignedType(int8_t);
DEFINE_isSignedType(int16_t);

View File

@ -97,9 +97,9 @@ static void setup_sme_operand(MCInst *MI)
AArch64_get_detail_op(MI, 0)->sme.type = AARCH64_SME_OP_INVALID;
AArch64_get_detail_op(MI, 0)->sme.tile = AARCH64_REG_INVALID;
AArch64_get_detail_op(MI, 0)->sme.slice_reg = AARCH64_REG_INVALID;
AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm = -1;
AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm_range.first = -1;
AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm_range.offset = -1;
AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm = AARCH64_SLICE_IMM_INVALID;
AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm_range.first = AARCH64_SLICE_IMM_RANGE_INVALID;
AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm_range.offset = AARCH64_SLICE_IMM_RANGE_INVALID;
}
static void setup_pred_operand(MCInst *MI)
@ -556,6 +556,9 @@ static void AArch64_add_not_defined_ops(MCInst *MI, const SStream *OS)
default:
return;
case AARCH64_INS_ALIAS_FMOV:
if (AArch64_get_detail_op(MI, -1)->type == AARCH64_OP_FP) {
break;
}
AArch64_insert_detail_op_float_at(MI, -1, 0.0f, CS_AC_READ);
break;
case AARCH64_INS_ALIAS_LD1:
@ -1315,6 +1318,10 @@ static void add_cs_detail_general(MCInst *MI, aarch64_op_group op_group,
int64_t Offset = MCInst_getOpVal(MI, OpNum);
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
(MI->address & -4) + Offset);
} else {
// Expression
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
MCOperand_isImm(MCInst_getOperand(MI, OpNum)));
}
break;
}
@ -1323,11 +1330,18 @@ static void add_cs_detail_general(MCInst *MI, aarch64_op_group op_group,
int64_t Offset = MCInst_getOpVal(MI, OpNum) * 4096;
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
(MI->address & -4096) + Offset);
} else {
// Expression
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
MCOperand_isImm(MCInst_getOperand(MI, OpNum)));
}
break;
}
case AArch64_OP_GROUP_AdrAdrpLabel: {
if (!MCOperand_isImm(MCInst_getOperand(MI, OpNum))) {
// Expression
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
MCOperand_isImm(MCInst_getOperand(MI, OpNum)));
break;
}
int64_t Offset = MCInst_getOpVal(MI, OpNum);
@ -1345,6 +1359,10 @@ static void add_cs_detail_general(MCInst *MI, aarch64_op_group op_group,
int64_t Offset = MCInst_getOpVal(MI, OpNum) * 4;
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
MI->address + Offset);
} else {
// Expression
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
MCOperand_isImm(MCInst_getOperand(MI, OpNum)));
}
break;
}
@ -1502,7 +1520,7 @@ static void add_cs_detail_general(MCInst *MI, aarch64_op_group op_group,
AArch64_set_detail_op_sme(MI, OpNum,
AARCH64_SME_MATRIX_TILE_LIST,
AARCH64LAYOUT_VL_D,
AARCH64_REG_ZAD0 + I);
(int) (AARCH64_REG_ZAD0 + I));
AArch64_inc_op_count(MI);
}
break;
@ -1607,8 +1625,10 @@ static void add_cs_detail_general(MCInst *MI, aarch64_op_group op_group,
unsigned Val = MCInst_getOpVal(MI, OpNum);
const AArch64SVEPredPattern_SVEPREDPAT *Pat =
AArch64SVEPredPattern_lookupSVEPREDPATByEncoding(Val);
if (!Pat)
if (!Pat) {
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM, Val);
break;
}
aarch64_sysop sysop;
sysop.alias = Pat->SysAlias;
sysop.sub_type = AARCH64_OP_SVEPREDPAT;
@ -1738,6 +1758,7 @@ static void add_cs_detail_template_1(MCInst *MI, aarch64_op_group op_group,
(1 << AArch64_AM_getShiftValue(Shift));
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
Val);
break;
}
case AArch64_OP_GROUP_Imm8OptLsl_uint16_t:
case AArch64_OP_GROUP_Imm8OptLsl_uint32_t:
@ -1747,6 +1768,7 @@ static void add_cs_detail_template_1(MCInst *MI, aarch64_op_group op_group,
(1 << AArch64_AM_getShiftValue(Shift));
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
Val);
break;
}
}
break;
@ -1791,7 +1813,7 @@ static void add_cs_detail_template_1(MCInst *MI, aarch64_op_group op_group,
AArch64_set_detail_op_sme(MI, OpNum,
AARCH64_SME_MATRIX_SLICE_OFF,
AARCH64LAYOUT_INVALID,
MCInst_getOpVal(MI, OpNum) * scale);
(uint32_t) (MCInst_getOpVal(MI, OpNum) * scale));
} else if (AArch64_get_detail_op(MI, 0)->type == AARCH64_OP_PRED) {
// The index is part of a predicate
AArch64_set_detail_op_pred(MI, OpNum);
@ -1852,7 +1874,7 @@ static void add_cs_detail_template_1(MCInst *MI, aarch64_op_group op_group,
unsigned EltSize = temp_arg_0;
AArch64_get_detail_op(MI, 0)->vas = EltSize;
AArch64_set_detail_op_reg(
MI, OpNum, MCInst_getOpVal(MI, OpNum) - AArch64_P0);
MI, OpNum, MCInst_getOpVal(MI, OpNum) - AArch64_PN0);
break;
}
case AArch64_OP_GROUP_PrefetchOp_0:
@ -1925,7 +1947,8 @@ static void add_cs_detail_template_1(MCInst *MI, aarch64_op_group op_group,
case AArch64_OP_GROUP_UImm12Offset_2:
case AArch64_OP_GROUP_UImm12Offset_4:
case AArch64_OP_GROUP_UImm12Offset_8: {
unsigned Scale = temp_arg_0;
// Otherwise it is an expression. For which we only add the immediate
unsigned Scale = MCOperand_isImm(MCInst_getOperand(MI, OpNum)) ? temp_arg_0 : 1;
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
Scale * MCInst_getOpVal(MI, OpNum));
break;
@ -2050,6 +2073,7 @@ static void add_cs_detail_template_2(MCInst *MI, aarch64_op_group op_group,
case AArch64_OP_GROUP_TypedVectorList_0_h:
case AArch64_OP_GROUP_TypedVectorList_0_q:
case AArch64_OP_GROUP_TypedVectorList_0_s:
case AArch64_OP_GROUP_TypedVectorList_0_0:
case AArch64_OP_GROUP_TypedVectorList_16_b:
case AArch64_OP_GROUP_TypedVectorList_1_d:
case AArch64_OP_GROUP_TypedVectorList_2_d:
@ -2107,7 +2131,7 @@ static void add_cs_detail_template_2(MCInst *MI, aarch64_op_group op_group,
case 'q':
vas = AARCH64LAYOUT_VL_Q;
break;
case '\0':
case '0':
// Implicitly Typed register
break;
}
@ -2389,6 +2413,7 @@ void AArch64_add_cs_detail(MCInst *MI, int /* aarch64_op_group */ op_group,
case AArch64_OP_GROUP_TypedVectorList_0_h:
case AArch64_OP_GROUP_TypedVectorList_0_q:
case AArch64_OP_GROUP_TypedVectorList_0_s:
case AArch64_OP_GROUP_TypedVectorList_0_0:
case AArch64_OP_GROUP_TypedVectorList_16_b:
case AArch64_OP_GROUP_TypedVectorList_1_d:
case AArch64_OP_GROUP_TypedVectorList_2_d:
@ -2500,7 +2525,7 @@ void AArch64_set_detail_op_imm(MCInst *MI, unsigned OpNum,
if (AArch64_get_detail_op(MI, 0)->type == AARCH64_OP_SME) {
AArch64_set_detail_op_sme(MI, OpNum,
AARCH64_SME_MATRIX_SLICE_OFF,
AARCH64LAYOUT_INVALID, 1);
AARCH64LAYOUT_INVALID, (uint32_t) 1);
} else if (AArch64_get_detail_op(MI, 0)->type == AARCH64_OP_PRED) {
AArch64_set_detail_op_pred(MI, OpNum);
} else {
@ -2524,7 +2549,7 @@ void AArch64_set_detail_op_imm(MCInst *MI, unsigned OpNum,
}
void AArch64_set_detail_op_imm_range(MCInst *MI, unsigned OpNum,
int64_t FirstImm, int64_t Offset)
uint32_t FirstImm, uint32_t Offset)
{
if (!detail_is_set(MI))
return;
@ -2534,8 +2559,8 @@ void AArch64_set_detail_op_imm_range(MCInst *MI, unsigned OpNum,
if (AArch64_get_detail_op(MI, 0)->type == AARCH64_OP_SME) {
AArch64_set_detail_op_sme(MI, OpNum,
AARCH64_SME_MATRIX_SLICE_OFF_RANGE,
AARCH64LAYOUT_INVALID, FirstImm,
Offset);
AARCH64LAYOUT_INVALID, (uint32_t) FirstImm,
(uint32_t) Offset);
} else if (AArch64_get_detail_op(MI, 0)->type == AARCH64_OP_PRED) {
assert(0 && "Unkown SME predicate imm range type");
} else {
@ -2694,15 +2719,15 @@ void AArch64_set_detail_op_sme(MCInst *MI, unsigned OpNum,
if (!detail_is_set(MI))
return;
AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_SME;
va_list args;
switch (part) {
default:
printf("Unhandled SME operand part %d\n", part);
assert(0);
case AARCH64_SME_MATRIX_TILE_LIST:
case AARCH64_SME_MATRIX_TILE_LIST: {
setup_sme_operand(MI);
va_list args;
va_start(args, vas);
int Tile = va_arg(args, int);
int Tile = va_arg(args, int); // NOLINT(clang-analyzer-valist.Uninitialized)
va_end(args);
AArch64_get_detail_op(MI, 0)->sme.type = AARCH64_SME_OP_TILE;
AArch64_get_detail_op(MI, 0)->sme.tile = Tile;
@ -2710,6 +2735,7 @@ void AArch64_set_detail_op_sme(MCInst *MI, unsigned OpNum,
AArch64_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
AArch64_get_detail(MI)->is_doing_sme = true;
break;
}
case AARCH64_SME_MATRIX_TILE:
assert(map_get_op_type(MI, OpNum) == CS_OP_REG);
@ -2731,23 +2757,26 @@ void AArch64_set_detail_op_sme(MCInst *MI, unsigned OpNum,
AArch64_get_detail_op(MI, 0)->sme.slice_reg =
MCInst_getOpVal(MI, OpNum);
break;
case AARCH64_SME_MATRIX_SLICE_OFF:
case AARCH64_SME_MATRIX_SLICE_OFF: {
assert((map_get_op_type(MI, OpNum) & ~(CS_OP_MEM | CS_OP_BOUND)) == CS_OP_IMM);
// Because we took care of the slice register before, the op at -1 must be a SME operand.
assert(AArch64_get_detail_op(MI, 0)->type ==
AARCH64_OP_SME);
assert(AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm ==
-1);
AARCH64_SLICE_IMM_INVALID);
va_list args;
va_start(args, vas);
int64_t offset = va_arg(args, int64_t);
uint16_t offset = va_arg(args, uint32_t); // NOLINT(clang-analyzer-valist.Uninitialized)
va_end(args);
AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm =
offset;
break;
}
case AARCH64_SME_MATRIX_SLICE_OFF_RANGE: {
va_list args;
va_start(args, vas);
int8_t First = va_arg(args, int);
int8_t Offset = va_arg(args, int);
uint8_t First = va_arg(args, uint32_t); // NOLINT(clang-analyzer-valist.Uninitialized)
uint8_t Offset = va_arg(args, uint32_t); // NOLINT(clang-analyzer-valist.Uninitialized)
va_end(args);
AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm_range.first =
First;

View File

@ -56,7 +56,7 @@ void AArch64_set_detail_op_reg(MCInst *MI, unsigned OpNum, aarch64_reg Reg);
void AArch64_set_detail_op_imm(MCInst *MI, unsigned OpNum,
aarch64_op_type ImmType, int64_t Imm);
void AArch64_set_detail_op_imm_range(MCInst *MI, unsigned OpNum,
int64_t FirstImm, int64_t offset);
uint32_t FirstImm, uint32_t offset);
void AArch64_set_detail_op_mem(MCInst *MI, unsigned OpNum, uint64_t Val);
void AArch64_set_detail_op_mem_offset(MCInst *MI, unsigned OpNum, uint64_t Val);
void AArch64_set_detail_shift_ext(MCInst *MI, unsigned OpNum, bool SignExtend,

View File

@ -32,8 +32,11 @@ cs_err ALPHA_global_init(cs_struct *ud)
cs_err ALPHA_option(cs_struct *handle, cs_opt_type type, size_t value)
{
if (type == CS_OPT_SYNTAX)
if (type == CS_OPT_SYNTAX) {
handle->syntax = (int)value;
} else if (type == CS_OPT_MODE) {
handle->mode = (cs_mode)value;
}
return CS_ERR_OK;
}

View File

@ -278,10 +278,10 @@ static unsigned int peek_imm_16(const m68k_info *info) { return m68k_read_safe_1
static unsigned int peek_imm_32(const m68k_info *info) { return m68k_read_safe_32((info), (info)->pc); }
static unsigned long long peek_imm_64(const m68k_info *info) { return m68k_read_safe_64((info), (info)->pc); }
static unsigned int read_imm_8(m68k_info *info) { const unsigned int value = peek_imm_8(info); (info)->pc+=2; return value; }
static unsigned int read_imm_16(m68k_info *info) { const unsigned int value = peek_imm_16(info); (info)->pc+=2; return value; }
static unsigned int read_imm_32(m68k_info *info) { const unsigned int value = peek_imm_32(info); (info)->pc+=4; return value; }
static unsigned long long read_imm_64(m68k_info *info) { const unsigned long long value = peek_imm_64(info); (info)->pc+=8; return value; }
static unsigned int read_imm_8(m68k_info *info) { const unsigned int value = peek_imm_8(info); (info)->pc+=2; return value & 0xff; }
static unsigned int read_imm_16(m68k_info *info) { const unsigned int value = peek_imm_16(info); (info)->pc+=2; return value & 0xffff; }
static unsigned int read_imm_32(m68k_info *info) { const unsigned int value = peek_imm_32(info); (info)->pc+=4; return value & 0xffffffff; }
static unsigned long long read_imm_64(m68k_info *info) { const unsigned long long value = peek_imm_64(info); (info)->pc+=8; return value & 0xffffffffffffffff; }
/* Fake a split interface */
#define get_ea_mode_str_8(instruction) get_ea_mode_str(instruction, 0)
@ -472,9 +472,9 @@ static void get_ea_mode_op(m68k_info *info, cs_m68k_op* op, uint32_t instruction
op->type = M68K_OP_IMM;
if (size == 1)
op->imm = read_imm_8(info) & 0xff;
op->imm = read_imm_8(info);
else if (size == 2)
op->imm = read_imm_16(info) & 0xffff;
op->imm = read_imm_16(info);
else if (size == 4)
op->imm = read_imm_32(info);
else
@ -604,7 +604,7 @@ static void build_imm_ea(m68k_info *info, int opcode, uint8_t size, int imm)
op0->type = M68K_OP_IMM;
op0->address_mode = M68K_AM_IMMEDIATE;
op0->imm = imm;
op0->imm = imm & info->address_mask;
get_ea_mode_op(info, op1, info->ir, size);
}
@ -878,7 +878,8 @@ static uint16_t reverse_bits(uint32_t v)
s--;
}
return r <<= s; // shift when v's highest bits are zero
r <<= s; // shift when v's highest bits are zero
return r;
}
static uint8_t reverse_bits_8(uint32_t v)
@ -892,7 +893,8 @@ static uint8_t reverse_bits_8(uint32_t v)
s--;
}
return r <<= s; // shift when v's highest bits are zero
r <<= s; // shift when v's highest bits are zero
return r;
}

View File

@ -1,17 +1,6 @@
/* Capstone Disassembly Engine */
/* M68K Backend by Daniel Collin <daniel@collin.com> 2015-2016 */
#ifdef _MSC_VER
// Disable security warnings for strcat & sprintf
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
//Banned API Usage : strcat / sprintf is a Banned API as listed in dontuse.h for
//security purposes.
#pragma warning(disable:28719)
#endif
#include <stdio.h> // DEBUG
#include <stdlib.h>
#include <string.h>
@ -78,7 +67,7 @@ static const char* getRegName(m68k_reg reg)
return s_reg_names[(int)reg];
}
static void printRegbitsRange(char* buffer, uint32_t data, const char* prefix)
static void printRegbitsRange(char* buffer, size_t buf_len, uint32_t data, const char* prefix)
{
unsigned int first = 0;
unsigned int run_length = 0;
@ -95,11 +84,11 @@ static void printRegbitsRange(char* buffer, uint32_t data, const char* prefix)
}
if (buffer[0] != 0)
strcat(buffer, "/");
strncat(buffer, "/", buf_len - 1);
sprintf(buffer + strlen(buffer), "%s%d", prefix, first);
snprintf(buffer + strlen(buffer), buf_len, "%s%d", prefix, first);
if (run_length > 0)
sprintf(buffer + strlen(buffer), "-%s%d", prefix, first + run_length);
snprintf(buffer + strlen(buffer), buf_len, "-%s%d", prefix, first + run_length);
}
}
}
@ -116,9 +105,9 @@ static void registerBits(SStream* O, const cs_m68k_op* op)
return;
}
printRegbitsRange(buffer, data & 0xff, "d");
printRegbitsRange(buffer, (data >> 8) & 0xff, "a");
printRegbitsRange(buffer, (data >> 16) & 0xff, "fp");
printRegbitsRange(buffer, sizeof(buffer), data & 0xff, "d");
printRegbitsRange(buffer, sizeof(buffer), (data >> 8) & 0xff, "a");
printRegbitsRange(buffer, sizeof(buffer), (data >> 16) & 0xff, "fp");
SStream_concat(O, "%s", buffer);
}
@ -386,3 +375,24 @@ const char *M68K_group_name(csh handle, unsigned int id)
#endif
}
#ifndef CAPSTONE_DIET
void M68K_reg_access(const cs_insn *insn,
cs_regs regs_read, uint8_t *regs_read_count,
cs_regs regs_write, uint8_t *regs_write_count)
{
uint8_t read_count, write_count;
read_count = insn->detail->regs_read_count;
write_count = insn->detail->regs_write_count;
// implicit registers
memcpy(regs_read, insn->detail->regs_read,
read_count * sizeof(insn->detail->regs_read[0]));
memcpy(regs_write, insn->detail->regs_write,
write_count * sizeof(insn->detail->regs_write[0]));
*regs_read_count = read_count;
*regs_write_count = write_count;
}
#endif

View File

@ -17,5 +17,10 @@ void M68K_get_insn_id(cs_struct* h, cs_insn* insn, unsigned int id);
const char *M68K_insn_name(csh handle, unsigned int id);
const char* M68K_group_name(csh handle, unsigned int id);
void M68K_post_printer(csh handle, cs_insn* flat_insn, char* insn_asm, MCInst* mci);
#ifndef CAPSTONE_DIET
void M68K_reg_access(const cs_insn *insn,
cs_regs regs_read, uint8_t *regs_read_count,
cs_regs regs_write, uint8_t *regs_write_count);
#endif
#endif

View File

@ -13,7 +13,7 @@ cs_err M68K_global_init(cs_struct *ud)
{
m68k_info *info;
info = cs_mem_malloc(sizeof(m68k_info));
info = cs_mem_calloc(sizeof(m68k_info), 1);
if (!info) {
return CS_ERR_MEM;
}
@ -29,6 +29,9 @@ cs_err M68K_global_init(cs_struct *ud)
ud->insn_id = M68K_get_insn_id;
ud->insn_name = M68K_insn_name;
ud->group_name = M68K_group_name;
#ifndef CAPSTONE_DIET
ud->reg_access = M68K_reg_access;
#endif
return CS_ERR_OK;
}

View File

@ -33,8 +33,11 @@ cs_err RISCV_global_init(cs_struct * ud)
cs_err RISCV_option(cs_struct * handle, cs_opt_type type, size_t value)
{
if (type == CS_OPT_SYNTAX)
if (type == CS_OPT_SYNTAX) {
handle->syntax = (int)value;
} else if (type == CS_OPT_MODE) {
handle->mode = (cs_mode)value;
}
return CS_ERR_OK;
}

View File

@ -35,8 +35,11 @@ cs_err TRICORE_global_init(cs_struct *ud)
cs_err TRICORE_option(cs_struct *handle, cs_opt_type type, size_t value)
{
if (type == CS_OPT_SYNTAX)
if (type == CS_OPT_SYNTAX) {
handle->syntax = (int)value;
} else if (type == CS_OPT_MODE) {
handle->mode = (cs_mode)value;
}
return CS_ERR_OK;
}

View File

@ -288,9 +288,7 @@ static void get_op_access(cs_struct *h, unsigned int id, uint8_t *access, uint64
// initialize access
memset(access, 0, CS_X86_MAXIMUM_OPERAND_SIZE * sizeof(access[0]));
if (!arr) {
access[0] = 0;
return;
}
@ -302,7 +300,7 @@ static void get_op_access(cs_struct *h, unsigned int id, uint8_t *access, uint64
// copy in reverse order this access array from Intel syntax -> AT&T syntax
count--;
for(i = 0; i <= count; i++) {
for(i = 0; i <= count && ((count - i) < CS_X86_MAXIMUM_OPERAND_SIZE) && i < CS_X86_MAXIMUM_OPERAND_SIZE; i++) {
if (arr[count - i] != CS_AC_IGNORE)
access[i] = arr[count - i];
else

View File

@ -1,150 +0,0 @@
TMPDIR = /tmp/capstone_test
DIFF = diff -u -w
TEST_BASIC = $(TMPDIR)/test_basic
TEST_DETAIL = $(TMPDIR)/test_detail
TEST_CUSTOMIZED_MNEM = $(TMPDIR)/test_customized_mnem
TEST_ARM = $(TMPDIR)/test_arm
TEST_ARM64 = $(TMPDIR)/test_aarch64
TEST_M68K = $(TMPDIR)/test_m68k
TEST_MIPS = $(TMPDIR)/test_mips
TEST_MOS65XX = $(TMPDIR)/test_mos65xx
TEST_PPC = $(TMPDIR)/test_ppc
TEST_SPARC = $(TMPDIR)/test_sparc
TEST_SYSZ = $(TMPDIR)/test_systemz
TEST_X86 = $(TMPDIR)/test_x86
TEST_XCORE = $(TMPDIR)/test_xcore
TEST_WASM = $(TMPDIR)/test_wasm
TEST_BPF = $(TMPDIR)/test_bpf
TEST_RISCV = $(TMPDIR)/test_riscv
TEST_EVM = $(TMPDIR)/test_evm
TEST_M680X = $(TMPDIR)/test_m680x
TEST_TRICORE = $(TMPDIR)/test_tricore
TEST_SH = $(TMPDIR)/test_sh
TEST_TMS320C64X = $(TMPDIR)/test_tms320c64x
TEST_ALPHA = $(TMPDIR)/test_alpha
TEST_HPPA = $(TMPDIR)/test_hppa
PYTHON3 ?= python3
BUILD_TESTS ?= yes
.PHONY: all expected python java ocaml
all:
cd python && $(MAKE) gen_const
cd java && $(MAKE) gen_const
cd ocaml && $(MAKE) gen_const
tests: expected python #java oclma ruby
test_java: expected java
test_python: expected python
expected:
if [ "$(BUILD_TESTS)" = "yes" ]; then cd ../tests && $(MAKE); fi
mkdir -p $(TMPDIR)
../tests/test_basic > $(TEST_BASIC)_e
../tests/test_detail > $(TEST_DETAIL)_e
../tests/test_customized_mnem > $(TEST_CUSTOMIZED_MNEM)_e
../tests/test_arm > $(TEST_ARM)_e
../tests/test_aarch64 > $(TEST_ARM64)_e
../tests/test_m68k > $(TEST_M68K)_e
../tests/test_mips > $(TEST_MIPS)_e
../tests/test_mos65xx > $(TEST_MOS65XX)_e
../tests/test_ppc > $(TEST_PPC)_e
../tests/test_sparc > $(TEST_SPARC)_e
../tests/test_systemz > $(TEST_SYSZ)_e
../tests/test_x86 > $(TEST_X86)_e
../tests/test_xcore > $(TEST_XCORE)_e
../tests/test_wasm > $(TEST_WASM)_e
../tests/test_bpf > $(TEST_BPF)_e
../tests/test_riscv > $(TEST_RISCV)_e
../tests/test_evm > $(TEST_EVM)_e
../tests/test_m680x > $(TEST_M680X)_e
../tests/test_sh > $(TEST_SH)_e
../tests/test_tricore > $(TEST_TRICORE)_e
../tests/test_tms320c64x > $(TEST_TMS320C64X)_e
../tests/test_alpha > $(TEST_ALPHA)_e
../tests/test_hppa > $(TEST_HPPA)_e
python: FORCE
cd python && $(MAKE)
$(PYTHON3) python/test_basic.py > $(TEST_BASIC)_o
$(PYTHON3) python/test_detail.py > $(TEST_DETAIL)_o
$(PYTHON3) python/test_customized_mnem.py > $(TEST_CUSTOMIZED_MNEM)_o
$(PYTHON3) python/test_arm.py > $(TEST_ARM)_o
$(PYTHON3) python/test_aarch64.py > $(TEST_ARM64)_o
$(PYTHON3) python/test_m68k.py > $(TEST_M68K)_o
$(PYTHON3) python/test_mips.py > $(TEST_MIPS)_o
$(PYTHON3) python/test_mos65xx.py > $(TEST_MOS65XX)_o
$(PYTHON3) python/test_ppc.py > $(TEST_PPC)_o
$(PYTHON3) python/test_sparc.py > $(TEST_SPARC)_o
$(PYTHON3) python/test_systemz.py > $(TEST_SYSZ)_o
$(PYTHON3) python/test_x86.py > $(TEST_X86)_o
$(PYTHON3) python/test_xcore.py > $(TEST_XCORE)_o
$(PYTHON3) python/test_wasm.py > $(TEST_WASM)_o
$(PYTHON3) python/test_bpf.py > $(TEST_BPF)_o
$(PYTHON3) python/test_riscv.py > $(TEST_RISCV)_o
$(PYTHON3) python/test_evm.py > $(TEST_EVM)_o
$(PYTHON3) python/test_m680x.py > $(TEST_M680X)_o
$(PYTHON3) python/test_sh.py > $(TEST_SH)_o
$(PYTHON3) python/test_tricore.py > $(TEST_TRICORE)_o
$(PYTHON3) python/test_tms320c64x.py > $(TEST_TMS320C64X)_o
$(PYTHON3) python/test_alpha.py > $(TEST_ALPHA)_o
$(PYTHON3) python/test_hppa.py > $(TEST_HPPA)_o
$(MAKE) test_diff
java: FORCE
cd java && $(MAKE)
cd java && ./run.sh > $(TEST_BASIC)_o
cd java && ./run.sh arm > $(TEST_ARM)_o
cd java && ./run.sh arm64 > $(TEST_ARM64)_o
cd java && ./run.sh mips > $(TEST_MIPS)_o
cd java && ./run.sh ppc > $(TEST_PPC)_o
cd java && ./run.sh sparc > $(TEST_SPARC)_o
cd java && ./run.sh systemz > $(TEST_SYSZ)_o
cd java && ./run.sh x86 > $(TEST_X86)_o
cd java && ./run.sh xcore > $(TEST_XCORE)_o
$(MAKE) test_diff
ocaml: FORCE
test_diff: FORCE
$(DIFF) $(TEST_BASIC)_e $(TEST_BASIC)_o
$(DIFF) $(TEST_DETAIL)_e $(TEST_DETAIL)_o
$(DIFF) $(TEST_CUSTOMIZED_MNEM)_e $(TEST_CUSTOMIZED_MNEM)_o
$(DIFF) $(TEST_ARM)_e $(TEST_ARM)_o
$(DIFF) $(TEST_ARM64)_e $(TEST_ARM64)_o
$(DIFF) $(TEST_M68K)_e $(TEST_M68K)_o
$(DIFF) $(TEST_MIPS)_e $(TEST_MIPS)_o
$(DIFF) $(TEST_MOS65XX)_e $(TEST_MOS65XX)_o
$(DIFF) $(TEST_PPC)_e $(TEST_PPC)_o
$(DIFF) $(TEST_SPARC)_e $(TEST_SPARC)_o
$(DIFF) $(TEST_SYSZ)_e $(TEST_SYSZ)_o
$(DIFF) $(TEST_X86)_e $(TEST_X86)_o
$(DIFF) $(TEST_XCORE)_e $(TEST_XCORE)_o
$(DIFF) $(TEST_WASM)_e $(TEST_WASM)_o
$(DIFF) $(TEST_BPF)_e $(TEST_BPF)_o
$(DIFF) $(TEST_RISCV)_e $(TEST_RISCV)_o
$(DIFF) $(TEST_EVM)_e $(TEST_EVM)_o
$(DIFF) $(TEST_M680X)_e $(TEST_M680X)_o
$(DIFF) $(TEST_SH)_e $(TEST_SH)_o
$(DIFF) $(TEST_TRICORE)_e $(TEST_TRICORE)_o
$(DIFF) $(TEST_TMS320C64X)_e $(TEST_TMS320C64X)_o
$(DIFF) $(TEST_ALPHA)_e $(TEST_ALPHA)_o
$(DIFF) $(TEST_HPPA)_e $(TEST_HPPA)_o
clean:
rm -rf $(TMPDIR)
cd java && $(MAKE) clean
cd python && $(MAKE) clean
cd ocaml && $(MAKE) clean
check:
make -C ocaml check
make -C python check
make -C java check
FORCE:

View File

@ -1,11 +1,12 @@
# Capstone Disassembler Engine
# By Dang Hoang Vu, 2013
from __future__ import print_function
import sys, re
import sys
import re
INCL_DIR = '../include/capstone/'
include = [ 'arm.h', 'aarch64.h', 'm68k.h', 'mips.h', 'x86.h', 'ppc.h', 'sparc.h', 'systemz.h', 'xcore.h', 'tms320c64x.h', 'm680x.h', 'evm.h', 'mos65xx.h', 'wasm.h', 'bpf.h' ,'riscv.h', 'sh.h', 'tricore.h', 'alpha.h', 'hppa.h' ]
include = [ 'arm.h', 'aarch64.h', 'm68k.h', 'mips.h', 'x86.h', 'ppc.h', 'sparc.h', 'systemz.h', 'xcore.h', 'tms320c64x.h', 'm680x.h', 'evm.h', 'mos65xx.h', 'wasm.h', 'bpf.h' ,'riscv.h', 'sh.h', 'tricore.h', 'alpha.h', 'hppa.h', 'loongarch.h' ]
template = {
'java': {
@ -56,6 +57,7 @@ template = {
'tricore.h': ['TRICORE', 'TriCore'],
'alpha.h': ['ALPHA', 'Alpha'],
'hppa.h': 'hppa',
'loongarch.h': 'loongarch',
'comment_open': '#',
'comment_close': '',
},
@ -80,81 +82,6 @@ template = {
'comment_open': '(*',
'comment_close': ' *)',
},
# 'swift': {
# 'header': "// For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT (%s)\n\n",
# 'footer': "",
# 'enum_doc': '/// %s\n',
# 'enum_header': 'public enum %s: %s {\n',
# 'enum_default_type': 'UInt32',
# 'enum_types': {
# 'UInt16': r'^\w+Reg$',
# 'UInt8': r'^\w+Grp$'
# },
# 'option_set_header': 'public struct %s: OptionSet {\n public typealias RawValue = %s\n public let rawValue: RawValue\n public init(rawValue: RawValue) { self.rawValue = rawValue }\n',
# 'option_sets': {
# 'X86Eflags': 'UInt64',
# 'X86FpuFlags': 'UInt64',
# 'SparcHint': 'UInt32',
# 'M680xIdx': 'UInt8',
# 'M680xOpFlags': 'UInt8',
# },
# 'rename': {
# r'^M680X_(\w+_OP_IN_MNEM)$': r'M680X_OP_FLAGS_\1',
# },
# 'option_format': ' public static let {option} = {type}(rawValue: {value})\n',
# 'enum_extra_options': {
# # swift enum != OptionSet, so options must be specified
# 'ArmSysreg': {
# 'spsrCx': 'spsrC + spsrX',
# 'spsrCs': 'spsrC + spsrS',
# 'spsrXs': 'spsrX + spsrS',
# 'spsrCxs': 'spsrC + spsrX + spsrS',
# 'spsrCf': 'spsrC + spsrF',
# 'spsrXf': 'spsrX + spsrF',
# 'spsrCxf': 'spsrC + spsrX + spsrF',
# 'spsrSf': 'spsrS + spsrF',
# 'spsrCsf': 'spsrC + spsrS + spsrF',
# 'spsrXsf': 'spsrX + spsrS + spsrF',
# 'spsrCxsf': 'spsrC + spsrX + spsrS + spsrF',
# 'cpsrCx': 'cpsrC + cpsrX',
# 'cpsrCs': 'cpsrC + cpsrS',
# 'cpsrXs': 'cpsrX + cpsrS',
# 'cpsrCxs': 'cpsrC + cpsrX + cpsrS',
# 'cpsrCf': 'cpsrC + cpsrF',
# 'cpsrXf': 'cpsrX + cpsrF',
# 'cpsrCxf': 'cpsrC + cpsrX + cpsrF',
# 'cpsrSf': 'cpsrS + cpsrF',
# 'cpsrCsf': 'cpsrC + cpsrS + cpsrF',
# 'cpsrXsf': 'cpsrX + cpsrS + cpsrF',
# 'cpsrCxsf': 'cpsrC + cpsrX + cpsrS + cpsrF',
# }
# },
# 'enum_footer': '}\n\n',
# 'doc_line_format': ' /// %s\n',
# 'line_format': ' case %s = %s\n',
# 'dup_line_format': ' public static let %s = %s\n',
# 'out_file': './swift/Sources/Capstone/%sEnums.swift',
# 'reserved_words': [
# 'break', 'class', 'for', 'false', 'in', 'init', 'return', 'true'
# ],
# 'reserved_word_format': '`%s`',
# # prefixes for constant filenames of all archs - case sensitive
# 'arm.h': 'Arm',
# 'arm64.h': 'Arm64',
# 'm68k.h': 'M68k',
# 'mips.h': 'Mips',
# 'x86.h': 'X86',
# 'ppc.h': 'Ppc',
# 'sparc.h': 'Sparc',
# 'systemz.h': 'Sysz',
# 'xcore.h': 'Xcore',
# 'tms320c64x.h': 'TMS320C64x',
# 'm680x.h': 'M680x',
# 'evm.h': 'Evm',
# 'mos65xx.h': 'Mos65xx',
# 'comment_open': '\t//',
# 'comment_close': '',
# },
}
excluded_prefixes = {
@ -237,6 +164,11 @@ def gen(lang):
elif line.startswith('}') or line.startswith('#'):
doc_lines = []
pass
elif re.search(r"^(\s*typedef\s+)?enum", line):
# First new enum value should be 0.
# Because `rhs` is incremented later, it must be set to -1 here.
# Everything about this code is so broken -.-
rhs = "-1"
if line == '' or line.startswith('//'):
continue
@ -251,7 +183,7 @@ def gen(lang):
xline.insert(1, '=') # insert an = so the expression below can parse it
line = ' '.join(xline)
def is_with_prefix(x):
def has_special_arch_prefix(x):
if target in excluded_prefixes and any(x.startswith(excl_pre) for excl_pre in excluded_prefixes[target]):
return False
if prefixs:
@ -259,7 +191,7 @@ def gen(lang):
else:
return x.startswith(prefix.upper())
if not is_with_prefix(line):
if not has_special_arch_prefix(line):
continue
tmp = line.strip().split(',')
@ -271,7 +203,7 @@ def gen(lang):
t = re.sub(r'\((\d+)ULL << (\d+)\)', r'\1 << \2', t) # (1ULL<<1) to 1 << 1
f = re.split('\s+', t)
if not is_with_prefix(f[0]):
if not has_special_arch_prefix(f[0]):
continue
if len(f) > 1 and f[1] not in ('//', '///<', '='):

View File

@ -1,6 +1,5 @@
MANIFEST
dist/
src/
capstone/lib
capstone/include
pyx/lib

View File

@ -4,17 +4,12 @@
1. To install Capstone and the Python bindings on *nix, run the command below:
$ sudo make install
To control the install destination, set the DESTDIR environment variable.
```
pip install bindings/python/
```
2. The tests directory contains some test code to show how to use the Capstone API.
- test_basic.py
This code shows the most simple form of API where we only want to get basic
information out of disassembled instruction, such as address, mnemonic and
operand string.
- test_lite.py
Similarly to test_basic.py, but this code shows how to use disasm_lite(), a lighter
method to disassemble binary. Unlike disasm() API (used by test_basic.py), which returns
@ -23,12 +18,3 @@
The main reason for using this API is better performance: disasm_lite() is at least
20% faster than disasm(). Memory usage is also less. So if you just need basic
information out of disassembler, use disasm_lite() instead of disasm().
- test_detail.py:
This code shows how to access to architecture-neutral information in disassembled
instructions, such as implicit registers read/written, or groups of instructions
that this instruction belong to.
- test_<arch>.py
These code show how to access architecture-specific information for each
architecture.

View File

@ -40,6 +40,7 @@ __all__ = [
'CS_ARCH_TRICORE',
'CS_ARCH_ALPHA',
'CS_ARCH_HPPA',
'CS_ARCH_LOONGARCH',
'CS_ARCH_ALL',
'CS_MODE_LITTLE_ENDIAN',
@ -107,6 +108,8 @@ __all__ = [
'CS_MODE_HPPA_11',
'CS_MODE_HPPA_20',
'CS_MODE_HPPA_20W',
'CS_MODE_LOONGARCH32',
'CS_MODE_LOONGARCH64',
'CS_OPT_SYNTAX',
'CS_OPT_SYNTAX_DEFAULT',
@ -225,6 +228,7 @@ CS_ARCH_SH = 16
CS_ARCH_TRICORE = 17
CS_ARCH_ALPHA = 18
CS_ARCH_HPPA = 19
CS_ARCH_LOONGARCH = 20
CS_ARCH_MAX = 20
CS_ARCH_ALL = 0xFFFF
@ -294,6 +298,8 @@ CS_MODE_TRICORE_162 = 1 << 7 # Tricore 1.6.2
CS_MODE_HPPA_11 = 1 << 1 # HPPA 1.1
CS_MODE_HPPA_20 = 1 << 2 # HPPA 2.0
CS_MODE_HPPA_20W = CS_MODE_HPPA_20 | (1 << 3) # HPPA 2.0 wide
CS_MODE_LOONGARCH32 = 1 << 0
CS_MODE_LOONGARCH64 = 1 << 1
# Capstone option type
CS_OPT_INVALID = 0 # No option specified
@ -347,16 +353,18 @@ CS_GRP_BRANCH_RELATIVE = 7 # all relative branching instructions
CS_AC_INVALID = 0 # Invalid/uninitialized access type.
CS_AC_READ = (1 << 0) # Operand that is read from.
CS_AC_WRITE = (1 << 1) # Operand that is written to.
CS_AC_READ_WRITE = (2)
CS_AC_READ_WRITE = CS_AC_READ | CS_AC_WRITE
# Capstone syntax value
CS_OPT_SYNTAX_DEFAULT = 1 << 1 # Default assembly syntax of all platforms (CS_OPT_SYNTAX)
CS_OPT_SYNTAX_INTEL = 1 << 2 # Intel X86 asm syntax - default syntax on X86 (CS_OPT_SYNTAX, CS_ARCH_X86)
CS_OPT_SYNTAX_ATT = 1 << 3 # ATT asm syntax (CS_OPT_SYNTAX, CS_ARCH_X86)
CS_OPT_SYNTAX_NOREGNAME = 1 << 4 # Asm syntax prints register name with only number - (CS_OPT_SYNTAX, CS_ARCH_PPC, CS_ARCH_ARM)
CS_OPT_SYNTAX_MASM = 1 << 5 # MASM syntax (CS_OPT_SYNTAX, CS_ARCH_X86)
CS_OPT_SYNTAX_MOTOROLA = 1 << 6 # MOS65XX use $ as hex prefix
CS_OPT_SYNTAX_CS_REG_ALIAS = 1 << 7 # Prints common register alias which are not defined in LLVM (ARM: r9 = sb etc.)
CS_OPT_SYNTAX_DEFAULT = (1 << 1) # Default assembly syntax of all platforms (CS_OPT_SYNTAX)
CS_OPT_SYNTAX_INTEL = (1 << 2) # Intel X86 asm syntax - default syntax on X86 (CS_OPT_SYNTAX, CS_ARCH_X86)
CS_OPT_SYNTAX_ATT = (1 << 3) # ATT asm syntax (CS_OPT_SYNTAX, CS_ARCH_X86)
CS_OPT_SYNTAX_NOREGNAME = (1 << 4) # Asm syntax prints register name with only number - (CS_OPT_SYNTAX, CS_ARCH_PPC, CS_ARCH_ARM)
CS_OPT_SYNTAX_MASM = (1 << 5) # MASM syntax (CS_OPT_SYNTAX, CS_ARCH_X86)
CS_OPT_SYNTAX_MOTOROLA = (1 << 6) # MOS65XX use $ as hex prefix
CS_OPT_SYNTAX_CS_REG_ALIAS = (1 << 7) # Prints common register alias which are not defined in LLVM (ARM: r9 = sb etc.)
CS_OPT_SYNTAX_PERCENT = (1 << 8) # Prints the % in front of PPC registers.
CS_OPT_DETAIL_REAL = (1 << 1) # If enabled, always sets the real instruction detail.Even if the instruction is an alias.
# Capstone error type
CS_ERR_OK = 0 # No error: everything was fine
@ -460,7 +468,7 @@ def copy_ctypes_list(src):
return [copy_ctypes(n) for n in src]
# Weird import placement because these modules are needed by the below code but need the above functions
from . import arm, aarch64, m68k, mips, ppc, sparc, systemz, x86, xcore, tms320c64x, m680x, evm, mos65xx, wasm, bpf, riscv, sh, tricore, alpha, hppa
from . import arm, aarch64, m68k, mips, ppc, sparc, systemz, x86, xcore, tms320c64x, m680x, evm, mos65xx, wasm, bpf, riscv, sh, tricore, alpha, hppa, loongarch
class _cs_arch(ctypes.Union):
_fields_ = (
@ -484,6 +492,7 @@ class _cs_arch(ctypes.Union):
('tricore', tricore.CsTriCore),
('alpha', alpha.CsAlpha),
('hppa', hppa.CsHPPA),
('loongarch', loongarch.CsLoongArch),
)
class _cs_detail(ctypes.Structure):
@ -695,6 +704,21 @@ class CsInsn(object):
def size(self):
return self._raw.size
# return instruction's is_alias flag
@property
def is_alias(self):
return self._raw.is_alias
# return instruction's alias_id
@property
def alias_id(self):
return self._raw.alias_id
# return instruction's flag if it uses alias details
@property
def uses_alias_details(self):
return self._raw.usesAliasDetails
# return instruction's machine bytes (which should have @size bytes).
@property
def bytes(self):
@ -802,7 +826,7 @@ class CsInsn(object):
elif arch == CS_ARCH_MIPS:
self.operands = mips.get_arch_info(self._raw.detail.contents.arch.mips)
elif arch == CS_ARCH_PPC:
(self.bc, self.update_cr0, self.operands) = \
(self.bc, self.update_cr0, self.format, self.operands) = \
ppc.get_arch_info(self._raw.detail.contents.arch.ppc)
elif arch == CS_ARCH_SPARC:
(self.cc, self.hint, self.operands) = sparc.get_arch_info(self._raw.detail.contents.arch.sparc)
@ -832,6 +856,8 @@ class CsInsn(object):
(self.operands) = alpha.get_arch_info(self._raw.detail.contents.arch.alpha)
elif arch == CS_ARCH_HPPA:
(self.operands) = hppa.get_arch_info(self._raw.detail.contents.arch.hppa)
elif arch == CS_ARCH_LOONGARCH:
(self.format, self.operands) = loongarch.get_arch_info(self._raw.detail.contents.arch.loongarch)
def __getattr__(self, name):
@ -840,14 +866,14 @@ class CsInsn(object):
attr = object.__getattribute__
if not attr(self, '_cs')._detail:
raise AttributeError(name)
raise AttributeError(f"'CsInsn' has no attribute '{name}'")
_dict = attr(self, '__dict__')
if 'operands' not in _dict:
self.__gen_detail()
if name not in _dict:
if self._raw.id == 0:
raise CsError(CS_ERR_SKIPDATA)
raise AttributeError(name)
raise AttributeError(f"'CsInsn' has no attribute '{name}'")
return _dict[name]
# get the last error code
@ -1021,9 +1047,16 @@ class Cs(object):
except: # _cs might be pulled from under our feet
pass
# def option(self, opt_type, opt_value):
# return _cs.cs_option(self.csh, opt_type, opt_value)
def option(self, opt_type, opt_value):
status = _cs.cs_option(self.csh, opt_type, opt_value)
if status != CS_ERR_OK:
raise CsError(status)
if opt_type == CS_OPT_DETAIL:
self._detail = opt_value == CS_OPT_ON
elif opt_type == CS_OPT_SKIPDATA:
self._skipdata = opt_value == CS_OPT_ON
elif opt_type == CS_OPT_UNSIGNED:
self._imm_unsigned = opt_value == CS_OPT_ON
# is this a diet engine?
@ -1321,7 +1354,7 @@ def debug():
"m680x": CS_ARCH_M680X, 'evm': CS_ARCH_EVM, 'mos65xx': CS_ARCH_MOS65XX,
'bpf': CS_ARCH_BPF, 'riscv': CS_ARCH_RISCV, 'tricore': CS_ARCH_TRICORE,
'wasm': CS_ARCH_WASM, 'sh': CS_ARCH_SH, 'alpha': CS_ARCH_ALPHA,
'hppa': CS_ARCH_HPPA
'hppa': CS_ARCH_HPPA, 'loongarch': CS_ARCH_LOONGARCH
}
all_archs = ""

View File

@ -14,7 +14,7 @@ class AArch64OpMem(ctypes.Structure):
class AArch64ImmRange(ctypes.Structure):
_fields_ = (
('imm', ctypes.c_int8),
('first', ctypes.c_int8),
('offset', ctypes.c_int8),
)

File diff suppressed because it is too large Load Diff

View File

@ -76,164 +76,166 @@ Alpha_REG_R31 = 64
Alpha_REG_ENDING = 65
# Alpha instruction
Alpha_INS_INVALID = 66
Alpha_INS_ADDL = 67
Alpha_INS_ADDQ = 68
Alpha_INS_ADDSsSU = 69
Alpha_INS_ADDTsSU = 70
Alpha_INS_AND = 71
Alpha_INS_BEQ = 72
Alpha_INS_BGE = 73
Alpha_INS_BGT = 74
Alpha_INS_BIC = 75
Alpha_INS_BIS = 76
Alpha_INS_BLBC = 77
Alpha_INS_BLBS = 78
Alpha_INS_BLE = 79
Alpha_INS_BLT = 80
Alpha_INS_BNE = 81
Alpha_INS_BR = 82
Alpha_INS_BSR = 83
Alpha_INS_CMOVEQ = 84
Alpha_INS_CMOVGE = 85
Alpha_INS_CMOVGT = 86
Alpha_INS_CMOVLBC = 87
Alpha_INS_CMOVLBS = 88
Alpha_INS_CMOVLE = 89
Alpha_INS_CMOVLT = 90
Alpha_INS_CMOVNE = 91
Alpha_INS_CMPBGE = 92
Alpha_INS_CMPEQ = 93
Alpha_INS_CMPLE = 94
Alpha_INS_CMPLT = 95
Alpha_INS_CMPTEQsSU = 96
Alpha_INS_CMPTLEsSU = 97
Alpha_INS_CMPTLTsSU = 98
Alpha_INS_CMPTUNsSU = 99
Alpha_INS_CMPULE = 100
Alpha_INS_CMPULT = 101
Alpha_INS_COND_BRANCH = 102
Alpha_INS_CPYSE = 103
Alpha_INS_CPYSN = 104
Alpha_INS_CPYS = 105
Alpha_INS_CTLZ = 106
Alpha_INS_CTPOP = 107
Alpha_INS_CTTZ = 108
Alpha_INS_CVTQSsSUI = 109
Alpha_INS_CVTQTsSUI = 110
Alpha_INS_CVTSTsS = 111
Alpha_INS_CVTTQsSVC = 112
Alpha_INS_CVTTSsSUI = 113
Alpha_INS_DIVSsSU = 114
Alpha_INS_DIVTsSU = 115
Alpha_INS_ECB = 116
Alpha_INS_EQV = 117
Alpha_INS_EXCB = 118
Alpha_INS_EXTBL = 119
Alpha_INS_EXTLH = 120
Alpha_INS_EXTLL = 121
Alpha_INS_EXTQH = 122
Alpha_INS_EXTQL = 123
Alpha_INS_EXTWH = 124
Alpha_INS_EXTWL = 125
Alpha_INS_FBEQ = 126
Alpha_INS_FBGE = 127
Alpha_INS_FBGT = 128
Alpha_INS_FBLE = 129
Alpha_INS_FBLT = 130
Alpha_INS_FBNE = 131
Alpha_INS_FCMOVEQ = 132
Alpha_INS_FCMOVGE = 133
Alpha_INS_FCMOVGT = 134
Alpha_INS_FCMOVLE = 135
Alpha_INS_FCMOVLT = 136
Alpha_INS_FCMOVNE = 137
Alpha_INS_FETCH = 138
Alpha_INS_FETCH_M = 139
Alpha_INS_FTOIS = 140
Alpha_INS_FTOIT = 141
Alpha_INS_INSBL = 142
Alpha_INS_INSLH = 143
Alpha_INS_INSLL = 144
Alpha_INS_INSQH = 145
Alpha_INS_INSQL = 146
Alpha_INS_INSWH = 147
Alpha_INS_INSWL = 148
Alpha_INS_ITOFS = 149
Alpha_INS_ITOFT = 150
Alpha_INS_JMP = 151
Alpha_INS_JSR = 152
Alpha_INS_JSR_COROUTINE = 153
Alpha_INS_LDA = 154
Alpha_INS_LDAH = 155
Alpha_INS_LDBU = 156
Alpha_INS_LDL = 157
Alpha_INS_LDL_L = 158
Alpha_INS_LDQ = 159
Alpha_INS_LDQ_L = 160
Alpha_INS_LDQ_U = 161
Alpha_INS_LDS = 162
Alpha_INS_LDT = 163
Alpha_INS_LDWU = 164
Alpha_INS_MB = 165
Alpha_INS_MSKBL = 166
Alpha_INS_MSKLH = 167
Alpha_INS_MSKLL = 168
Alpha_INS_MSKQH = 169
Alpha_INS_MSKQL = 170
Alpha_INS_MSKWH = 171
Alpha_INS_MSKWL = 172
Alpha_INS_MULL = 173
Alpha_INS_MULQ = 174
Alpha_INS_MULSsSU = 175
Alpha_INS_MULTsSU = 176
Alpha_INS_ORNOT = 177
Alpha_INS_RC = 178
Alpha_INS_RET = 179
Alpha_INS_RPCC = 180
Alpha_INS_RS = 181
Alpha_INS_S4ADDL = 182
Alpha_INS_S4ADDQ = 183
Alpha_INS_S4SUBL = 184
Alpha_INS_S4SUBQ = 185
Alpha_INS_S8ADDL = 186
Alpha_INS_S8ADDQ = 187
Alpha_INS_S8SUBL = 188
Alpha_INS_S8SUBQ = 189
Alpha_INS_SEXTB = 190
Alpha_INS_SEXTW = 191
Alpha_INS_SLL = 192
Alpha_INS_SQRTSsSU = 193
Alpha_INS_SQRTTsSU = 194
Alpha_INS_SRA = 195
Alpha_INS_SRL = 196
Alpha_INS_STB = 197
Alpha_INS_STL = 198
Alpha_INS_STL_C = 199
Alpha_INS_STQ = 200
Alpha_INS_STQ_C = 201
Alpha_INS_STQ_U = 202
Alpha_INS_STS = 203
Alpha_INS_STT = 204
Alpha_INS_STW = 205
Alpha_INS_SUBL = 206
Alpha_INS_SUBQ = 207
Alpha_INS_SUBSsSU = 208
Alpha_INS_SUBTsSU = 209
Alpha_INS_TRAPB = 210
Alpha_INS_UMULH = 211
Alpha_INS_WH64 = 212
Alpha_INS_WH64EN = 213
Alpha_INS_WMB = 214
Alpha_INS_XOR = 215
Alpha_INS_ZAPNOT = 216
ALPHA_INS_ENDING = 217
Alpha_INS_INVALID = 0
Alpha_INS_ADDL = 1
Alpha_INS_ADDQ = 2
Alpha_INS_ADDSsSU = 3
Alpha_INS_ADDTsSU = 4
Alpha_INS_AND = 5
Alpha_INS_BEQ = 6
Alpha_INS_BGE = 7
Alpha_INS_BGT = 8
Alpha_INS_BIC = 9
Alpha_INS_BIS = 10
Alpha_INS_BLBC = 11
Alpha_INS_BLBS = 12
Alpha_INS_BLE = 13
Alpha_INS_BLT = 14
Alpha_INS_BNE = 15
Alpha_INS_BR = 16
Alpha_INS_BSR = 17
Alpha_INS_CMOVEQ = 18
Alpha_INS_CMOVGE = 19
Alpha_INS_CMOVGT = 20
Alpha_INS_CMOVLBC = 21
Alpha_INS_CMOVLBS = 22
Alpha_INS_CMOVLE = 23
Alpha_INS_CMOVLT = 24
Alpha_INS_CMOVNE = 25
Alpha_INS_CMPBGE = 26
Alpha_INS_CMPEQ = 27
Alpha_INS_CMPLE = 28
Alpha_INS_CMPLT = 29
Alpha_INS_CMPTEQsSU = 30
Alpha_INS_CMPTLEsSU = 31
Alpha_INS_CMPTLTsSU = 32
Alpha_INS_CMPTUNsSU = 33
Alpha_INS_CMPULE = 34
Alpha_INS_CMPULT = 35
Alpha_INS_COND_BRANCH = 36
Alpha_INS_CPYSE = 37
Alpha_INS_CPYSN = 38
Alpha_INS_CPYS = 39
Alpha_INS_CTLZ = 40
Alpha_INS_CTPOP = 41
Alpha_INS_CTTZ = 42
Alpha_INS_CVTQSsSUI = 43
Alpha_INS_CVTQTsSUI = 44
Alpha_INS_CVTSTsS = 45
Alpha_INS_CVTTQsSVC = 46
Alpha_INS_CVTTSsSUI = 47
Alpha_INS_DIVSsSU = 48
Alpha_INS_DIVTsSU = 49
Alpha_INS_ECB = 50
Alpha_INS_EQV = 51
Alpha_INS_EXCB = 52
Alpha_INS_EXTBL = 53
Alpha_INS_EXTLH = 54
Alpha_INS_EXTLL = 55
Alpha_INS_EXTQH = 56
Alpha_INS_EXTQL = 57
Alpha_INS_EXTWH = 58
Alpha_INS_EXTWL = 59
Alpha_INS_FBEQ = 60
Alpha_INS_FBGE = 61
Alpha_INS_FBGT = 62
Alpha_INS_FBLE = 63
Alpha_INS_FBLT = 64
Alpha_INS_FBNE = 65
Alpha_INS_FCMOVEQ = 66
Alpha_INS_FCMOVGE = 67
Alpha_INS_FCMOVGT = 68
Alpha_INS_FCMOVLE = 69
Alpha_INS_FCMOVLT = 70
Alpha_INS_FCMOVNE = 71
Alpha_INS_FETCH = 72
Alpha_INS_FETCH_M = 73
Alpha_INS_FTOIS = 74
Alpha_INS_FTOIT = 75
Alpha_INS_INSBL = 76
Alpha_INS_INSLH = 77
Alpha_INS_INSLL = 78
Alpha_INS_INSQH = 79
Alpha_INS_INSQL = 80
Alpha_INS_INSWH = 81
Alpha_INS_INSWL = 82
Alpha_INS_ITOFS = 83
Alpha_INS_ITOFT = 84
Alpha_INS_JMP = 85
Alpha_INS_JSR = 86
Alpha_INS_JSR_COROUTINE = 87
Alpha_INS_LDA = 88
Alpha_INS_LDAH = 89
Alpha_INS_LDBU = 90
Alpha_INS_LDL = 91
Alpha_INS_LDL_L = 92
Alpha_INS_LDQ = 93
Alpha_INS_LDQ_L = 94
Alpha_INS_LDQ_U = 95
Alpha_INS_LDS = 96
Alpha_INS_LDT = 97
Alpha_INS_LDWU = 98
Alpha_INS_MB = 99
Alpha_INS_MSKBL = 100
Alpha_INS_MSKLH = 101
Alpha_INS_MSKLL = 102
Alpha_INS_MSKQH = 103
Alpha_INS_MSKQL = 104
Alpha_INS_MSKWH = 105
Alpha_INS_MSKWL = 106
Alpha_INS_MULL = 107
Alpha_INS_MULQ = 108
Alpha_INS_MULSsSU = 109
Alpha_INS_MULTsSU = 110
Alpha_INS_ORNOT = 111
Alpha_INS_RC = 112
Alpha_INS_RET = 113
Alpha_INS_RPCC = 114
Alpha_INS_RS = 115
Alpha_INS_S4ADDL = 116
Alpha_INS_S4ADDQ = 117
Alpha_INS_S4SUBL = 118
Alpha_INS_S4SUBQ = 119
Alpha_INS_S8ADDL = 120
Alpha_INS_S8ADDQ = 121
Alpha_INS_S8SUBL = 122
Alpha_INS_S8SUBQ = 123
Alpha_INS_SEXTB = 124
Alpha_INS_SEXTW = 125
Alpha_INS_SLL = 126
Alpha_INS_SQRTSsSU = 127
Alpha_INS_SQRTTsSU = 128
Alpha_INS_SRA = 129
Alpha_INS_SRL = 130
Alpha_INS_STB = 131
Alpha_INS_STL = 132
Alpha_INS_STL_C = 133
Alpha_INS_STQ = 134
Alpha_INS_STQ_C = 135
Alpha_INS_STQ_U = 136
Alpha_INS_STS = 137
Alpha_INS_STT = 138
Alpha_INS_STW = 139
Alpha_INS_SUBL = 140
Alpha_INS_SUBQ = 141
Alpha_INS_SUBSsSU = 142
Alpha_INS_SUBTsSU = 143
Alpha_INS_TRAPB = 144
Alpha_INS_UMULH = 145
Alpha_INS_WH64 = 146
Alpha_INS_WH64EN = 147
Alpha_INS_WMB = 148
Alpha_INS_XOR = 149
Alpha_INS_ZAPNOT = 150
ALPHA_INS_ENDING = 151
# Group of Alpha instructions
Alpha_GRP_INVALID = 218
Alpha_GRP_INVALID = 0
# Generic groups
Alpha_GRP_CALL = 219
Alpha_GRP_JUMP = 220
Alpha_GRP_BRANCH_RELATIVE = 221
Alpha_GRP_ENDING = 222
Alpha_GRP_CALL = 1
Alpha_GRP_JUMP = 2
Alpha_GRP_BRANCH_RELATIVE = 3
Alpha_GRP_ENDING = 4

View File

@ -12,6 +12,7 @@ class ArmOpMem(ctypes.Structure):
('scale', ctypes.c_int),
('disp', ctypes.c_int),
('lshift', ctypes.c_int),
('align', ctypes.c_uint),
)
class ArmOpShift(ctypes.Structure):
@ -38,7 +39,7 @@ class ArmOpValue(ctypes.Union):
_fields_ = (
('reg', ctypes.c_uint),
('sysop', ArmOpSysop),
('imm', ctypes.c_int32),
('imm', ctypes.c_int64),
('pred', ctypes.c_int),
('fp', ctypes.c_double),
('mem', ArmOpMem),

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,55 @@
# Copyright © 2024 Rot127 <unisono@quyllur.org>
# SPDX-License-Identifier: BSD-3
import ctypes
from . import copy_ctypes_list
from .loongarch_const import *
class LoongArchOpMem(ctypes.Structure):
_fields_ = (
("base", ctypes.c_uint),
("index", ctypes.c_uint),
("disp", ctypes.c_int64),
)
class LoongArchOpValue(ctypes.Union):
_fields_ = (
("reg", ctypes.c_uint),
("imm", ctypes.c_int64),
("mem", LoongArchOpMem),
)
class LoongArchOp(ctypes.Structure):
_fields_ = (
("type", ctypes.c_uint8),
("value", LoongArchOpValue),
("access", ctypes.c_uint8),
)
@property
def imm(self):
return self.value.imm
@property
def reg(self):
return self.value.reg
@property
def mem(self):
return self.value.mem
# Instruction structure
class CsLoongArch(ctypes.Structure):
_fields_ = (
("format", ctypes.c_int),
("op_count", ctypes.c_uint8),
("operands", LoongArchOp * 8)
)
def get_arch_info(a):
return a.format, copy_ctypes_list(a.operands[: a.op_count])

File diff suppressed because it is too large Load Diff

View File

@ -60,5 +60,5 @@ class CsPpc(ctypes.Structure):
)
def get_arch_info(a):
return (a.bc, a.update_cr0, copy_ctypes_list(a.operands[:a.op_count]))
return (a.bc, a.update_cr0, a.format, copy_ctypes_list(a.operands[:a.op_count]))

File diff suppressed because it is too large Load Diff

View File

@ -140,10 +140,11 @@ SH_OP_MEM_GBR_DISP = 6
SH_OP_MEM_GBR_R0 = 7
SH_OP_MEM_PCR = 8
SH_OP_MEM_TBR_DISP = 9
SH_INS_DSP_INVALID = 10
SH_INS_DSP_DOUBLE = 11
SH_INS_DSP_SINGLE = 12
SH_INS_DSP_PARALLEL = 13
SH_INS_DSP_INVALID = 0
SH_INS_DSP_DOUBLE = 1
SH_INS_DSP_SINGLE = 2
SH_INS_DSP_PARALLEL = 3
SH_INS_DSP_NOP = 1
SH_INS_DSP_MOV = 2
SH_INS_DSP_PSHL = 3
@ -174,177 +175,180 @@ SH_INS_DSP_PLDS = 27
SH_INS_DSP_PSWAP = 28
SH_INS_DSP_PWAD = 29
SH_INS_DSP_PWSB = 30
SH_OP_DSP_INVALID = 31
SH_OP_DSP_REG_PRE = 32
SH_OP_DSP_REG_IND = 33
SH_OP_DSP_REG_POST = 34
SH_OP_DSP_REG_INDEX = 35
SH_OP_DSP_REG = 36
SH_OP_DSP_IMM = 37
SH_DSP_CC_INVALID = 38
SH_DSP_CC_NONE = 39
SH_DSP_CC_DCT = 40
SH_DSP_CC_DCF = 41
SH_INS_INVALID = 42
SH_INS_ADD_r = 43
SH_INS_ADD = 44
SH_INS_ADDC = 45
SH_INS_ADDV = 46
SH_INS_AND = 47
SH_INS_BAND = 48
SH_INS_BANDNOT = 49
SH_INS_BCLR = 50
SH_INS_BF = 51
SH_INS_BF_S = 52
SH_INS_BLD = 53
SH_INS_BLDNOT = 54
SH_INS_BOR = 55
SH_INS_BORNOT = 56
SH_INS_BRA = 57
SH_INS_BRAF = 58
SH_INS_BSET = 59
SH_INS_BSR = 60
SH_INS_BSRF = 61
SH_INS_BST = 62
SH_INS_BT = 63
SH_INS_BT_S = 64
SH_INS_BXOR = 65
SH_INS_CLIPS = 66
SH_INS_CLIPU = 67
SH_INS_CLRDMXY = 68
SH_INS_CLRMAC = 69
SH_INS_CLRS = 70
SH_INS_CLRT = 71
SH_INS_CMP_EQ = 72
SH_INS_CMP_GE = 73
SH_INS_CMP_GT = 74
SH_INS_CMP_HI = 75
SH_INS_CMP_HS = 76
SH_INS_CMP_PL = 77
SH_INS_CMP_PZ = 78
SH_INS_CMP_STR = 79
SH_INS_DIV0S = 80
SH_INS_DIV0U = 81
SH_INS_DIV1 = 82
SH_INS_DIVS = 83
SH_INS_DIVU = 84
SH_INS_DMULS_L = 85
SH_INS_DMULU_L = 86
SH_INS_DT = 87
SH_INS_EXTS_B = 88
SH_INS_EXTS_W = 89
SH_INS_EXTU_B = 90
SH_INS_EXTU_W = 91
SH_INS_FABS = 92
SH_INS_FADD = 93
SH_INS_FCMP_EQ = 94
SH_INS_FCMP_GT = 95
SH_INS_FCNVDS = 96
SH_INS_FCNVSD = 97
SH_INS_FDIV = 98
SH_INS_FIPR = 99
SH_INS_FLDI0 = 100
SH_INS_FLDI1 = 101
SH_INS_FLDS = 102
SH_INS_FLOAT = 103
SH_INS_FMAC = 104
SH_INS_FMOV = 105
SH_INS_FMUL = 106
SH_INS_FNEG = 107
SH_INS_FPCHG = 108
SH_INS_FRCHG = 109
SH_INS_FSCA = 110
SH_INS_FSCHG = 111
SH_INS_FSQRT = 112
SH_INS_FSRRA = 113
SH_INS_FSTS = 114
SH_INS_FSUB = 115
SH_INS_FTRC = 116
SH_INS_FTRV = 117
SH_INS_ICBI = 118
SH_INS_JMP = 119
SH_INS_JSR = 120
SH_INS_JSR_N = 121
SH_INS_LDBANK = 122
SH_INS_LDC = 123
SH_INS_LDRC = 124
SH_INS_LDRE = 125
SH_INS_LDRS = 126
SH_INS_LDS = 127
SH_INS_LDTLB = 128
SH_INS_MAC_L = 129
SH_INS_MAC_W = 130
SH_INS_MOV = 131
SH_INS_MOVA = 132
SH_INS_MOVCA = 133
SH_INS_MOVCO = 134
SH_INS_MOVI20 = 135
SH_INS_MOVI20S = 136
SH_INS_MOVLI = 137
SH_INS_MOVML = 138
SH_INS_MOVMU = 139
SH_INS_MOVRT = 140
SH_INS_MOVT = 141
SH_INS_MOVU = 142
SH_INS_MOVUA = 143
SH_INS_MUL_L = 144
SH_INS_MULR = 145
SH_INS_MULS_W = 146
SH_INS_MULU_W = 147
SH_INS_NEG = 148
SH_INS_NEGC = 149
SH_INS_NOP = 150
SH_INS_NOT = 151
SH_INS_NOTT = 152
SH_INS_OCBI = 153
SH_INS_OCBP = 154
SH_INS_OCBWB = 155
SH_INS_OR = 156
SH_INS_PREF = 157
SH_INS_PREFI = 158
SH_INS_RESBANK = 159
SH_INS_ROTCL = 160
SH_INS_ROTCR = 161
SH_INS_ROTL = 162
SH_INS_ROTR = 163
SH_INS_RTE = 164
SH_INS_RTS = 165
SH_INS_RTS_N = 166
SH_INS_RTV_N = 167
SH_INS_SETDMX = 168
SH_INS_SETDMY = 169
SH_INS_SETRC = 170
SH_INS_SETS = 171
SH_INS_SETT = 172
SH_INS_SHAD = 173
SH_INS_SHAL = 174
SH_INS_SHAR = 175
SH_INS_SHLD = 176
SH_INS_SHLL = 177
SH_INS_SHLL16 = 178
SH_INS_SHLL2 = 179
SH_INS_SHLL8 = 180
SH_INS_SHLR = 181
SH_INS_SHLR16 = 182
SH_INS_SHLR2 = 183
SH_INS_SHLR8 = 184
SH_INS_SLEEP = 185
SH_INS_STBANK = 186
SH_INS_STC = 187
SH_INS_STS = 188
SH_INS_SUB = 189
SH_INS_SUBC = 190
SH_INS_SUBV = 191
SH_INS_SWAP_B = 192
SH_INS_SWAP_W = 193
SH_INS_SYNCO = 194
SH_INS_TAS = 195
SH_INS_TRAPA = 196
SH_INS_TST = 197
SH_INS_XOR = 198
SH_INS_XTRCT = 199
SH_INS_DSP = 200
SH_INS_ENDING = 201
SH_OP_DSP_INVALID = 0
SH_OP_DSP_REG_PRE = 1
SH_OP_DSP_REG_IND = 2
SH_OP_DSP_REG_POST = 3
SH_OP_DSP_REG_INDEX = 4
SH_OP_DSP_REG = 5
SH_OP_DSP_IMM = 6
SH_DSP_CC_INVALID = 0
SH_DSP_CC_NONE = 1
SH_DSP_CC_DCT = 2
SH_DSP_CC_DCF = 3
SH_INS_INVALID = 0
SH_INS_ADD_r = 1
SH_INS_ADD = 2
SH_INS_ADDC = 3
SH_INS_ADDV = 4
SH_INS_AND = 5
SH_INS_BAND = 6
SH_INS_BANDNOT = 7
SH_INS_BCLR = 8
SH_INS_BF = 9
SH_INS_BF_S = 10
SH_INS_BLD = 11
SH_INS_BLDNOT = 12
SH_INS_BOR = 13
SH_INS_BORNOT = 14
SH_INS_BRA = 15
SH_INS_BRAF = 16
SH_INS_BSET = 17
SH_INS_BSR = 18
SH_INS_BSRF = 19
SH_INS_BST = 20
SH_INS_BT = 21
SH_INS_BT_S = 22
SH_INS_BXOR = 23
SH_INS_CLIPS = 24
SH_INS_CLIPU = 25
SH_INS_CLRDMXY = 26
SH_INS_CLRMAC = 27
SH_INS_CLRS = 28
SH_INS_CLRT = 29
SH_INS_CMP_EQ = 30
SH_INS_CMP_GE = 31
SH_INS_CMP_GT = 32
SH_INS_CMP_HI = 33
SH_INS_CMP_HS = 34
SH_INS_CMP_PL = 35
SH_INS_CMP_PZ = 36
SH_INS_CMP_STR = 37
SH_INS_DIV0S = 38
SH_INS_DIV0U = 39
SH_INS_DIV1 = 40
SH_INS_DIVS = 41
SH_INS_DIVU = 42
SH_INS_DMULS_L = 43
SH_INS_DMULU_L = 44
SH_INS_DT = 45
SH_INS_EXTS_B = 46
SH_INS_EXTS_W = 47
SH_INS_EXTU_B = 48
SH_INS_EXTU_W = 49
SH_INS_FABS = 50
SH_INS_FADD = 51
SH_INS_FCMP_EQ = 52
SH_INS_FCMP_GT = 53
SH_INS_FCNVDS = 54
SH_INS_FCNVSD = 55
SH_INS_FDIV = 56
SH_INS_FIPR = 57
SH_INS_FLDI0 = 58
SH_INS_FLDI1 = 59
SH_INS_FLDS = 60
SH_INS_FLOAT = 61
SH_INS_FMAC = 62
SH_INS_FMOV = 63
SH_INS_FMUL = 64
SH_INS_FNEG = 65
SH_INS_FPCHG = 66
SH_INS_FRCHG = 67
SH_INS_FSCA = 68
SH_INS_FSCHG = 69
SH_INS_FSQRT = 70
SH_INS_FSRRA = 71
SH_INS_FSTS = 72
SH_INS_FSUB = 73
SH_INS_FTRC = 74
SH_INS_FTRV = 75
SH_INS_ICBI = 76
SH_INS_JMP = 77
SH_INS_JSR = 78
SH_INS_JSR_N = 79
SH_INS_LDBANK = 80
SH_INS_LDC = 81
SH_INS_LDRC = 82
SH_INS_LDRE = 83
SH_INS_LDRS = 84
SH_INS_LDS = 85
SH_INS_LDTLB = 86
SH_INS_MAC_L = 87
SH_INS_MAC_W = 88
SH_INS_MOV = 89
SH_INS_MOVA = 90
SH_INS_MOVCA = 91
SH_INS_MOVCO = 92
SH_INS_MOVI20 = 93
SH_INS_MOVI20S = 94
SH_INS_MOVLI = 95
SH_INS_MOVML = 96
SH_INS_MOVMU = 97
SH_INS_MOVRT = 98
SH_INS_MOVT = 99
SH_INS_MOVU = 100
SH_INS_MOVUA = 101
SH_INS_MUL_L = 102
SH_INS_MULR = 103
SH_INS_MULS_W = 104
SH_INS_MULU_W = 105
SH_INS_NEG = 106
SH_INS_NEGC = 107
SH_INS_NOP = 108
SH_INS_NOT = 109
SH_INS_NOTT = 110
SH_INS_OCBI = 111
SH_INS_OCBP = 112
SH_INS_OCBWB = 113
SH_INS_OR = 114
SH_INS_PREF = 115
SH_INS_PREFI = 116
SH_INS_RESBANK = 117
SH_INS_ROTCL = 118
SH_INS_ROTCR = 119
SH_INS_ROTL = 120
SH_INS_ROTR = 121
SH_INS_RTE = 122
SH_INS_RTS = 123
SH_INS_RTS_N = 124
SH_INS_RTV_N = 125
SH_INS_SETDMX = 126
SH_INS_SETDMY = 127
SH_INS_SETRC = 128
SH_INS_SETS = 129
SH_INS_SETT = 130
SH_INS_SHAD = 131
SH_INS_SHAL = 132
SH_INS_SHAR = 133
SH_INS_SHLD = 134
SH_INS_SHLL = 135
SH_INS_SHLL16 = 136
SH_INS_SHLL2 = 137
SH_INS_SHLL8 = 138
SH_INS_SHLR = 139
SH_INS_SHLR16 = 140
SH_INS_SHLR2 = 141
SH_INS_SHLR8 = 142
SH_INS_SLEEP = 143
SH_INS_STBANK = 144
SH_INS_STC = 145
SH_INS_STS = 146
SH_INS_SUB = 147
SH_INS_SUBC = 148
SH_INS_SUBV = 149
SH_INS_SWAP_B = 150
SH_INS_SWAP_W = 151
SH_INS_SYNCO = 152
SH_INS_TAS = 153
SH_INS_TRAPA = 154
SH_INS_TST = 155
SH_INS_XOR = 156
SH_INS_XTRCT = 157
SH_INS_DSP = 158
SH_INS_ENDING = 159
SH_GRP_INVALID = 0
SH_GRP_JUMP = 1

View File

@ -39,6 +39,8 @@ SPARC_HINT_INVALID = 0
SPARC_HINT_A = 1<<0
SPARC_HINT_PT = 1<<1
SPARC_HINT_PN = 1<<2
SPARC_HINT_A_PN = SPARC_HINT_A|SPARC_HINT_PN
SPARC_HINT_A_PT = SPARC_HINT_A|SPARC_HINT_PT
SPARC_OP_INVALID = 0
SPARC_OP_REG = 1

View File

@ -461,10 +461,11 @@ TRICORE_INS_XOR_LT = 388
TRICORE_INS_XOR_NE = 389
TRICORE_INS_XOR = 390
TRICORE_INS_ENDING = 391
TRICORE_GRP_INVALID = 392
TRICORE_GRP_CALL = 393
TRICORE_GRP_JUMP = 394
TRICORE_GRP_ENDING = 395
TRICORE_GRP_INVALID = 0
TRICORE_GRP_CALL = 1
TRICORE_GRP_JUMP = 2
TRICORE_GRP_ENDING = 3
TRICORE_FEATURE_INVALID = 0
TRICORE_FEATURE_HasV110 = 128

View File

@ -398,6 +398,7 @@ X86_AVX_RM_RN = 1
X86_AVX_RM_RD = 2
X86_AVX_RM_RU = 3
X86_AVX_RM_RZ = 4
X86_PREFIX_0 = 0x0
X86_PREFIX_LOCK = 0xf0
X86_PREFIX_REP = 0xf3
X86_PREFIX_REPE = 0xf3

View File

@ -0,0 +1,4 @@
## Python cstest
This is the equivalent testing tool to `suite/cstest/`. It consumes the `yaml` test files
in `<repo-root>/tests/` and reports the results.

View File

@ -0,0 +1,18 @@
# Copyright © 2024 Rot127 <unisono@quyllur.org>
# SPDX-License-Identifier: BSD-3
[project]
name = "cstest_py"
version = "0.1.0"
dependencies = [
"pyyaml >= 6.0.2",
"capstone >= 5.0.0",
]
requires-python = ">= 3.8"
[tool.setuptools]
packages = ["cstest_py"]
package-dir = {"" = "src"}
[project.scripts]
cstest_py = "cstest_py.cstest:main"

View File

@ -0,0 +1,337 @@
# Copyright © 2024 Rot127 <unisono@quyllur.org>
# SPDX-License-Identifier: BSD-3
# Typing for Python3.8
from __future__ import annotations
import struct
import capstone
import re
from capstone import arm_const
from capstone import aarch64_const
from capstone import m68k_const
from capstone import mips_const
from capstone import ppc_const
from capstone import sparc_const
from capstone import sysz_const
from capstone import x86_const
from capstone import xcore_const
from capstone import tms320c64x_const
from capstone import m680x_const
from capstone import evm_const
from capstone import mos65xx_const
from capstone import wasm_const
from capstone import bpf_const
from capstone import riscv_const
from capstone import sh_const
from capstone import tricore_const
from capstone import alpha_const
from capstone import hppa_const
from capstone import loongarch_const
def cs_const_getattr(identifier: str):
attr = getattr(capstone, identifier, None)
if attr is not None:
return attr
attr = getattr(arm_const, identifier, None)
if attr is not None:
return attr
attr = getattr(aarch64_const, identifier, None)
if attr is not None:
return attr
attr = getattr(m68k_const, identifier, None)
if attr is not None:
return attr
attr = getattr(mips_const, identifier, None)
if attr is not None:
return attr
attr = getattr(ppc_const, identifier, None)
if attr is not None:
return attr
attr = getattr(sparc_const, identifier, None)
if attr is not None:
return attr
attr = getattr(sysz_const, identifier, None)
if attr is not None:
return attr
attr = getattr(x86_const, identifier, None)
if attr is not None:
return attr
attr = getattr(xcore_const, identifier, None)
if attr is not None:
return attr
attr = getattr(tms320c64x_const, identifier, None)
if attr is not None:
return attr
attr = getattr(m680x_const, identifier, None)
if attr is not None:
return attr
attr = getattr(evm_const, identifier, None)
if attr is not None:
return attr
attr = getattr(mos65xx_const, identifier, None)
if attr is not None:
return attr
attr = getattr(wasm_const, identifier, None)
if attr is not None:
return attr
attr = getattr(bpf_const, identifier, None)
if attr is not None:
return attr
attr = getattr(riscv_const, identifier, None)
if attr is not None:
return attr
attr = getattr(sh_const, identifier, None)
if attr is not None:
return attr
attr = getattr(tricore_const, identifier, None)
if attr is not None:
return attr
attr = getattr(alpha_const, identifier, None)
if attr is not None:
return attr
attr = getattr(hppa_const, identifier, None)
if attr is not None:
return attr
attr = getattr(loongarch_const, identifier, None)
if attr is not None:
return attr
raise ValueError(f"Python capstone doesn't have the constant: {identifier}")
def twos_complement(val, bits):
if (val & (1 << (bits - 1))) != 0:
val = val - (1 << bits)
return val & ((1 << bits) - 1)
def normalize_asm_text(text: str, arch_bits: int) -> str:
text = text.strip()
text = re.sub(r"\s+", " ", text)
# Replace hex numbers with decimals
for hex_num in re.findall(r"0x[0-9a-fA-F]+", text):
text = re.sub(hex_num, f"{int(hex_num, base=16)}", text, count=1)
# Replace negatives with twos-complement
for num in re.findall(r"-\d+", text):
n = twos_complement(int(num, base=10), arch_bits)
text = re.sub(num, f"{n}", text)
text = text.lower()
return text
def compare_asm_text(
a_insn: capstone.CsInsn, expected: None | str, arch_bits: int
) -> bool:
if expected is None:
return True
from cstest_py.cstest import log
actual = f"{a_insn.mnemonic} {a_insn.op_str}"
actual = normalize_asm_text(actual, arch_bits)
expected = normalize_asm_text(expected, arch_bits)
if actual != expected:
log.error(
"Normalized asm-text doesn't match:\n"
f"decoded: '{actual}'\n"
f"expected: '{expected}'\n"
)
return False
return True
def compare_str(actual: str, expected: None | str, msg: str) -> bool:
if expected is None:
return True
from cstest_py.cstest import log
if actual != expected:
log.error(f"{msg}: {actual} != {expected}")
return False
return True
def compare_tbool(actual: bool, expected: None | int, msg: str) -> bool:
if expected is None:
return True
from cstest_py.cstest import log
if expected == 0:
# Unset
return True
if (expected < 0 and actual) or (expected > 0 and not actual):
log.error(f"{msg}: {actual} != {expected}")
return False
return True
def compare_uint8(actual: int, expected: None | int, msg: str) -> bool:
if expected is None:
return True
from cstest_py.cstest import log
actual = actual & 0xFF
expected = expected & 0xFF
if actual != expected:
log.error(f"{msg}: {actual} != {expected}")
return False
return True
def compare_int8(actual: int, expected: None | int, msg: str) -> bool:
if expected is None:
return True
from cstest_py.cstest import log
actual = actual & 0xFF
expected = expected & 0xFF
if actual != expected:
log.error(f"{msg}: {actual} != {expected}")
return False
return True
def compare_uint16(actual: int, expected: None | int, msg: str) -> bool:
if expected is None:
return True
from cstest_py.cstest import log
actual = actual & 0xFFFF
expected = expected & 0xFFFF
if actual != expected:
log.error(f"{msg}: {actual} != {expected}")
return False
return True
def compare_int16(actual: int, expected: None | int, msg: str) -> bool:
if expected is None:
return True
from cstest_py.cstest import log
actual = actual & 0xFFFF
expected = expected & 0xFFFF
if actual != expected:
log.error(f"{msg}: {actual} != {expected}")
return False
return True
def compare_uint32(actual: int, expected: None | int, msg: str) -> bool:
if expected is None:
return True
from cstest_py.cstest import log
actual = actual & 0xFFFFFFFF
expected = expected & 0xFFFFFFFF
if actual != expected:
log.error(f"{msg}: {actual} != {expected}")
return False
return True
def compare_int32(actual: int, expected: None | int, msg: str) -> bool:
if expected is None:
return True
from cstest_py.cstest import log
actual = actual & 0xFFFFFFFF
expected = expected & 0xFFFFFFFF
if actual != expected:
log.error(f"{msg}: {actual} != {expected}")
return False
return True
def compare_uint64(actual: int, expected: None | int, msg: str) -> bool:
if expected is None:
return True
from cstest_py.cstest import log
actual = actual & 0xFFFFFFFFFFFFFFFF
expected = expected & 0xFFFFFFFFFFFFFFFF
if actual != expected:
log.error(f"{msg}: {actual} != {expected}")
return False
return True
def compare_int64(actual: int, expected: None | int, msg: str) -> bool:
if expected is None:
return True
from cstest_py.cstest import log
actual = actual & 0xFFFFFFFFFFFFFFFF
expected = expected & 0xFFFFFFFFFFFFFFFF
if actual != expected:
log.error(f"{msg}: {actual} != {expected}")
return False
return True
def compare_fp(actual: float, expected: None | float, msg: str) -> bool:
if expected is None:
return True
from cstest_py.cstest import log
def floatToBits(f):
return struct.unpack("=L", struct.pack("=f", f))[0]
if floatToBits(actual) != floatToBits(expected):
log.error(f"{msg}: {actual} != {expected}")
return False
return True
def compare_dp(actual: float, expected: None | float, msg: str) -> bool:
if expected is None:
return True
from cstest_py.cstest import log
def doubleToBits(f):
return struct.unpack("=Q", struct.pack("=d", f))[0]
if doubleToBits(actual) != doubleToBits(expected):
log.error(f"{msg}: {actual} != {expected}")
return False
return True
def compare_enum(actual, expected: None | str, msg: str) -> bool:
if expected is None:
return True
from cstest_py.cstest import log
enum_val = cs_const_getattr(expected)
if actual != enum_val:
log.error(f"{msg}: {actual} != {expected} ({enum_val})")
return False
return True
def compare_bit_flags(actual: int, expected: None | list[str], msg: str) -> bool:
if expected is None:
return True
from cstest_py.cstest import log
for flag in expected:
enum_val = cs_const_getattr(flag)
if not actual & enum_val:
log.error(f"{msg}: In {actual:x} the flag {expected} isn't set.")
return False
return True
def compare_reg(
insn: capstone.CsInsn, actual: int, expected: None | str, msg: str
) -> bool:
if expected is None:
return True
from cstest_py.cstest import log
if insn.reg_name(actual) != expected:
log.error(f"{msg}: {actual} != {expected}")
return False
return True

View File

@ -0,0 +1,41 @@
# Copyright © 2024 Rot127 <unisono@quyllur.org>
# SPDX-License-Identifier: BSD-3
import capstone as cs
configs = {
"CS_OPT_DETAIL": {"type": cs.CS_OPT_DETAIL, "val": cs.CS_OPT_ON},
"CS_OPT_DETAIL_REAL": {
"type": cs.CS_OPT_DETAIL,
"val": cs.CS_OPT_DETAIL_REAL | cs.CS_OPT_ON,
},
"CS_OPT_SKIPDATA": {"type": cs.CS_OPT_SKIPDATA, "val": cs.CS_OPT_ON},
"CS_OPT_UNSIGNED": {"type": cs.CS_OPT_UNSIGNED, "val": cs.CS_OPT_ON},
"CS_OPT_NO_BRANCH_OFFSET": {
"type": cs.CS_OPT_NO_BRANCH_OFFSET,
"val": cs.CS_OPT_ON,
},
"CS_OPT_SYNTAX_DEFAULT": {
"type": cs.CS_OPT_SYNTAX,
"val": cs.CS_OPT_SYNTAX_DEFAULT,
},
"CS_OPT_SYNTAX_INTEL": {"type": cs.CS_OPT_SYNTAX, "val": cs.CS_OPT_SYNTAX_INTEL},
"CS_OPT_SYNTAX_ATT": {"type": cs.CS_OPT_SYNTAX, "val": cs.CS_OPT_SYNTAX_ATT},
"CS_OPT_SYNTAX_NOREGNAME": {
"type": cs.CS_OPT_SYNTAX,
"val": cs.CS_OPT_SYNTAX_NOREGNAME,
},
"CS_OPT_SYNTAX_MASM": {"type": cs.CS_OPT_SYNTAX, "val": cs.CS_OPT_SYNTAX_MASM},
"CS_OPT_SYNTAX_MOTOROLA": {
"type": cs.CS_OPT_SYNTAX,
"val": cs.CS_OPT_SYNTAX_MOTOROLA,
},
"CS_OPT_SYNTAX_CS_REG_ALIAS": {
"type": cs.CS_OPT_SYNTAX,
"val": cs.CS_OPT_SYNTAX_CS_REG_ALIAS,
},
"CS_OPT_SYNTAX_PERCENT": {
"type": cs.CS_OPT_SYNTAX,
"val": cs.CS_OPT_SYNTAX_PERCENT,
},
}

View File

@ -0,0 +1,493 @@
#!/usr/bin/env python3
# Copyright © 2024 Rot127 <unisono@quyllur.org>
# SPDX-License-Identifier: BSD-3
# Typing for Python3.8
from __future__ import annotations
import argparse
import logging
import subprocess as sp
import sys
import os
import yaml
import capstone
import traceback
from capstone import CsInsn, Cs, CS_ARCH_AARCH64, CS_MODE_64, CS_MODE_16
from cstest_py.cs_modes import configs
from cstest_py.details import compare_details
from cstest_py.compare import (
compare_asm_text,
compare_str,
compare_tbool,
compare_uint32,
)
from enum import Enum
from pathlib import Path
log = logging.getLogger("__name__")
def get_cs_int_attr(cs, attr: str, err_msg_pre: str):
try:
attr_int = getattr(cs, attr)
if not isinstance(attr_int, int):
raise AttributeError(f"{attr} not found")
return attr_int
except AttributeError:
log.warning(f"{err_msg_pre}: Capstone doesn't have the attribute '{attr}'")
return None
def arch_bits(arch: int, mode: int) -> int:
if arch == CS_ARCH_AARCH64 or mode & CS_MODE_64:
return 64
elif mode & CS_MODE_16:
return 16
return 32
class TestResult(Enum):
SUCCESS = 0
FAILED = 1
SKIPPED = 2
ERROR = 3
class TestStats:
def __init__(self, total_file_count: int):
self.total_file_count = total_file_count
self.valid_test_files = 0
self.test_case_count = 0
self.success = 0
self.failed = 0
self.skipped = 0
self.errors = 0
self.invalid_files = 0
self.total_valid_files = 0
self.err_msgs: list[str] = list()
self.failing_files = set()
def add_failing_file(self, test_file: Path):
self.failing_files.add(test_file)
def add_error_msg(self, msg: str):
self.err_msgs.append(msg)
def add_invalid_file_dp(self, tfile: Path):
self.invalid_files += 1
self.errors += 1
self.add_failing_file(tfile)
def add_test_case_data_point(self, dp: TestResult):
if dp == TestResult.SUCCESS:
self.success += 1
elif dp == TestResult.FAILED:
self.failed += 1
elif dp == TestResult.SKIPPED:
self.skipped += 1
elif dp == TestResult.ERROR:
self.errors += 1
self.failed += 1
else:
raise ValueError(f"Unhandled TestResult: {dp}")
def set_total_valid_files(self, total_valid_files: int):
self.total_valid_files = total_valid_files
def set_total_test_cases(self, total_test_cases: int):
self.test_case_count = total_test_cases
def get_test_case_count(self) -> int:
return self.test_case_count
def print_evaluate(self):
if self.total_file_count == 0:
log.error("No test files found!")
exit(-1)
if self.test_case_count == 0:
log.error("No test cases found!")
exit(-1)
if self.failing_files:
print("Test files with failures:")
for tf in self.failing_files:
print(f" - {tf}")
print()
if self.err_msgs:
print("Error messages:")
for error in self.err_msgs:
print(f" - {error}")
print("\n-----------------------------------------")
print("Test run statistics\n")
print(f"Valid files: {self.total_valid_files}")
print(f"Invalid files: {self.invalid_files}")
print(f"Errors: {self.errors}\n")
print("Test cases:")
print(f"\tTotal: {self.test_case_count}")
print(f"\tSuccessful: {self.success}")
print(f"\tSkipped: {self.skipped}")
print(f"\tFailed: {self.failed}")
print("-----------------------------------------")
print("")
if self.test_case_count != self.success + self.failed + self.skipped:
log.error(
"Inconsistent statistics: total != successful + failed + skipped\n"
)
if self.errors != 0:
log.error("Failed with errors\n")
exit(-1)
elif self.failed != 0:
log.warning("Not all tests succeeded\n")
exit(-1)
log.info("All tests succeeded.\n")
exit(0)
class TestInput:
def __init__(self, input_dict: dict):
self.input_dict = input_dict
if "bytes" not in self.input_dict:
raise ValueError("Error: 'Missing required mapping field'\nField: 'bytes'.")
if "options" not in self.input_dict:
raise ValueError(
"Error: 'Missing required mapping field'\nField: 'options'."
)
if "arch" not in self.input_dict:
raise ValueError("Error: 'Missing required mapping field'\nField: 'arch'.")
self.in_bytes = bytes(self.input_dict["bytes"])
self.options = self.input_dict["options"]
self.arch = self.input_dict["arch"]
self.name = "" if "name" not in self.input_dict else self.input_dict["name"]
if "address" not in self.input_dict:
self.address: int = 0
else:
assert isinstance(self.input_dict["address"], int)
self.address = self.input_dict["address"]
self.handle = None
self.arch_bits = 0
def setup(self):
log.debug(f"Init {self}")
arch = get_cs_int_attr(capstone, self.arch, "CS_ARCH")
if arch is None:
cs_name = f"CS_ARCH_{self.arch.upper()}"
arch = get_cs_int_attr(capstone, cs_name, "CS_ARCH")
if arch is None:
raise ValueError(
f"Couldn't init architecture as '{self.arch}' or '{cs_name}'.\n"
f"'{self.arch}' is not mapped to a capstone architecture."
)
new_mode = 0
for opt in self.options:
if "CS_MODE_" in opt:
mode = get_cs_int_attr(capstone, opt, "CS_OPT")
if mode is not None:
new_mode |= mode
continue
self.handle = Cs(arch, new_mode)
for opt in self.options:
if "CS_MODE_" in opt:
continue
if "CS_OPT_" in opt and opt in configs:
mtype = configs[opt]["type"]
val = configs[opt]["val"]
self.handle.option(mtype, val)
continue
log.warning(f"Option: '{opt}' not used")
self.arch_bits = arch_bits(self.handle.arch, self.handle.mode)
log.debug("Init done")
def decode(self) -> list[CsInsn]:
if not self.handle:
raise ValueError("self.handle is None. Must be setup before.")
return [i for i in self.handle.disasm(self.in_bytes, self.address)]
def __str__(self):
default = (
f"TestInput {{ arch: {self.arch}, options: {self.options}, "
f"addr: {self.address:x}, bytes: [ {','.join([f'{b:#04x}' for b in self.in_bytes])} ] }}"
)
if self.name:
return f"{self.name} -- {default}"
return default
class TestExpected:
def __init__(self, expected_dict: dict):
self.expected_dict = expected_dict
self.insns = (
list() if "insns" not in self.expected_dict else self.expected_dict["insns"]
)
def compare(self, actual_insns: list[CsInsn], bits: int) -> TestResult:
if len(actual_insns) != len(self.insns):
log.error(
"Number of decoded instructions don't match (actual != expected): "
f"{len(actual_insns)} != {len(self.insns):#x}"
)
return TestResult.FAILED
for a_insn, e_insn in zip(actual_insns, self.insns):
if not compare_asm_text(
a_insn,
e_insn.get("asm_text"),
bits,
):
return TestResult.FAILED
if not compare_str(a_insn.mnemonic, e_insn.get("mnemonic"), "mnemonic"):
return TestResult.FAILED
if not compare_str(a_insn.op_str, e_insn.get("op_str"), "op_str"):
return TestResult.FAILED
if not compare_uint32(a_insn.id, e_insn.get("id"), "id"):
return TestResult.FAILED
if not compare_tbool(a_insn.is_alias, e_insn.get("is_alias"), "is_alias"):
return TestResult.FAILED
if not compare_uint32(a_insn.alias_id, e_insn.get("alias_id"), "alias_id"):
return TestResult.FAILED
if not compare_details(a_insn, e_insn.get("details")):
return TestResult.FAILED
return TestResult.SUCCESS
class TestCase:
def __init__(self, test_case_dict: dict):
self.tc_dict = test_case_dict
if "input" not in self.tc_dict:
raise ValueError("Mandatory field 'input' missing")
if "expected" not in self.tc_dict:
raise ValueError("Mandatory field 'expected' missing")
self.input = TestInput(self.tc_dict["input"])
self.expected = TestExpected(self.tc_dict["expected"])
self.skip = "skip" in self.tc_dict
if self.skip and "skip_reason" not in self.tc_dict:
raise ValueError(
"If 'skip' field is set a 'skip_reason' field must be set as well."
)
self.skip_reason = (
self.tc_dict["skip_reason"] if "skip_reason" in self.tc_dict else ""
)
def __str__(self) -> str:
return f"{self.input}"
def test(self) -> TestResult:
if self.skip:
log.info(f"Skip {self}\nReason: {self.skip_reason}")
return TestResult.SKIPPED
try:
self.input.setup()
except Exception as e:
log.error(f"Setup failed at with: {e}")
traceback.print_exc()
return TestResult.ERROR
try:
insns = self.input.decode()
except Exception as e:
log.error(f"Decode failed with: {e}")
traceback.print_exc()
return TestResult.ERROR
try:
return self.expected.compare(insns, self.input.arch_bits)
except Exception as e:
log.error(f"Compare expected failed with: {e}")
traceback.print_exc()
return TestResult.ERROR
class TestFile:
def __init__(self, tfile_path: Path):
self.path = tfile_path
with open(tfile_path) as f:
try:
self.content = yaml.safe_load(f)
except yaml.YAMLError as e:
raise e
self.test_cases = list()
if not self.content:
raise ValueError("Empty file")
for tc_dict in self.content["test_cases"]:
tc = TestCase(tc_dict)
self.test_cases.append(tc)
def num_test_cases(self) -> int:
return len(self.test_cases)
def __str__(self) -> str:
return f"{self.path}"
class CSTest:
def __init__(self, path: Path, exclude: list[Path], include: list[Path]):
self.yaml_paths: list[Path] = list()
log.info(f"Search test files in {path}")
if path.is_file():
self.yaml_paths.append(path)
else:
for root, dirs, files in os.walk(path, onerror=print):
for file in files:
f = Path(root).joinpath(file)
if f.suffix not in [".yaml", ".yml"]:
continue
if f.name in exclude:
continue
if not include or f.name in include:
log.debug(f"Add: {f}")
self.yaml_paths.append(f)
log.info(f"Test files found: {len(self.yaml_paths)}")
self.stats = TestStats(len(self.yaml_paths))
self.test_files: list[TestFile] = list()
def parse_files(self):
total_test_cases = 0
total_files = len(self.yaml_paths)
count = 1
for tfile in self.yaml_paths:
print(
f"Parse {count}/{total_files}: {tfile.name}",
end=f"{' ' * 20}\r",
flush=True,
)
try:
tf = TestFile(tfile)
total_test_cases += tf.num_test_cases()
self.test_files.append(tf)
except yaml.YAMLError as e:
self.stats.add_error_msg(str(e))
self.stats.add_invalid_file_dp(tfile)
log.error("Error: 'libyaml parser error'")
log.error(f"{e}")
log.error(f"Failed to parse test file '{tfile}'")
except ValueError as e:
self.stats.add_error_msg(str(e))
self.stats.add_invalid_file_dp(tfile)
log.error(f"Error: ValueError: {e}")
log.error(f"Failed to parse test file '{tfile}'")
finally:
count += 1
self.stats.set_total_valid_files(len(self.test_files))
self.stats.set_total_test_cases(total_test_cases)
log.info(f"Found {self.stats.get_test_case_count()} test cases.{' ' * 20}")
def run_tests(self):
self.parse_files()
for tf in self.test_files:
log.info(f"Test file: {tf}\n")
for tc in tf.test_cases:
log.info(f"Run test: {tc}")
try:
result = tc.test()
except Exception as e:
result = TestResult.ERROR
self.stats.add_error_msg(str(e))
if result == TestResult.FAILED or result == TestResult.ERROR:
self.stats.add_failing_file(tf.path)
self.stats.add_test_case_data_point(result)
log.info(result)
print()
self.stats.print_evaluate()
def get_repo_root() -> str | None:
res = sp.run(["git", "rev-parse", "--show-toplevel"], capture_output=True)
if res.stderr:
log.error("Could not get repository root directory.")
return None
return res.stdout.decode("utf8").strip()
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(
prog="Python CSTest",
description="Pyton binding cstest implementation.",
)
repo_root = get_repo_root()
if repo_root:
parser.add_argument(
dest="search_dir",
help="Directory to search for .yaml test files.",
default=Path(f"{repo_root}/tests/"),
type=Path,
)
else:
parser.add_argument(
dest="search_dir",
help="Directory to search for .yaml test files.",
required=True,
type=Path,
)
parser.add_argument(
"-e",
dest="exclude",
help="List of file names to exclude.",
nargs="+",
required=False,
default=list(),
)
parser.add_argument(
"-i",
dest="include",
help="List of file names to include.",
nargs="+",
required=False,
default=list(),
)
parser.add_argument(
"-v",
dest="verbosity",
help="Verbosity of the log messages.",
choices=["debug", "info", "warning", "error", "fatal", "critical"],
default="info",
)
arguments = parser.parse_args()
return arguments
def main():
log_levels = {
"debug": logging.DEBUG,
"info": logging.INFO,
"warning": logging.WARNING,
"error": logging.ERROR,
"fatal": logging.FATAL,
"critical": logging.CRITICAL,
}
args = parse_args()
format = logging.Formatter("%(levelname)-5s - %(message)s", None, "%")
log.setLevel(log_levels[args.verbosity])
h1 = logging.StreamHandler(sys.stdout)
h1.addFilter(
lambda record: record.levelno >= log_levels[args.verbosity]
and record.levelno < logging.WARNING
)
h1.setFormatter(format)
h2 = logging.StreamHandler(sys.stderr)
h2.setLevel(logging.WARNING)
h2.setFormatter(format)
log.addHandler(h1)
log.addHandler(h2)
CSTest(args.search_dir, args.exclude, args.include).run_tests()
if __name__ == "__main__":
main()

File diff suppressed because it is too large Load Diff

View File

@ -72,10 +72,12 @@ else:
LIBRARY_FILE = "libcapstone.so"
STATIC_LIBRARY_FILE = 'libcapstone.a'
def clean_bins():
shutil.rmtree(LIBS_DIR, ignore_errors=True)
shutil.rmtree(HEADERS_DIR, ignore_errors=True)
def copy_sources():
"""Copy the C sources into the source directory.
This rearranges the source files under the python distribution
@ -92,22 +94,19 @@ def copy_sources():
shutil.copytree(os.path.join(BUILD_DIR, "include"), os.path.join(SRC_DIR, "include"))
src.extend(glob.glob(os.path.join(BUILD_DIR, "*.[ch]")))
src.extend(glob.glob(os.path.join(BUILD_DIR, "*.mk")))
src.extend(glob.glob(os.path.join(BUILD_DIR, "Makefile")))
src.extend(glob.glob(os.path.join(BUILD_DIR, "LICENSES/*")))
src.extend(glob.glob(os.path.join(BUILD_DIR, "README")))
src.extend(glob.glob(os.path.join(BUILD_DIR, "*.TXT")))
src.extend(glob.glob(os.path.join(BUILD_DIR, "RELEASE_NOTES")))
src.extend(glob.glob(os.path.join(BUILD_DIR, "make.sh")))
src.extend(glob.glob(os.path.join(BUILD_DIR, "CMakeLists.txt")))
src.extend(glob.glob(os.path.join(BUILD_DIR, "pkgconfig.mk")))
for filename in src:
outpath = os.path.join(SRC_DIR, os.path.basename(filename))
logger.info("%s -> %s" % (filename, outpath))
shutil.copy(filename, outpath)
def build_libraries():
"""
Prepare the capstone directory for a binary distribution or installation.
@ -134,23 +133,22 @@ def build_libraries():
os.chdir(BUILD_DIR)
# platform description refers at https://docs.python.org/3/library/sys.html#sys.platform
# Use cmake for both Darwin and Windows since it can generate fat binaries
if SYSTEM == "win32" or SYSTEM == 'darwin':
# Windows build: this process requires few things:
# - CMake + MSVC installed
# - Run this command in an environment setup for MSVC
if not os.path.exists("build"): os.mkdir("build")
os.chdir("build")
print("Build Directory: {}\n".format(os.getcwd()))
# Only build capstone.dll / libcapstone.dylib
if SYSTEM == "win32":
os.system('cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCAPSTONE_BUILD_TESTS=OFF -DCAPSTONE_BUILD_CSTOOL=OFF -G "NMake Makefiles" ..')
else:
os.system('cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCAPSTONE_BUILD_TESTS=OFF -DCAPSTONE_BUILD_CSTOOL=OFF -G "Unix Makefiles" ..')
os.system("cmake --build .")
else: # Unix incl. cygwin
os.system("CAPSTONE_BUILD_CORE_ONLY=yes bash ./make.sh")
# Windows build: this process requires few things:
# - MSVC installed
# - Run this command in an environment setup for MSVC
if not os.path.exists("build_py"):
os.mkdir("build_py")
os.chdir("build_py")
print("Build Directory: {}\n".format(os.getcwd()))
# Only build capstone.dll / libcapstone.dylib
if SYSTEM == "win32":
os.system('cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCAPSTONE_BUILD_LEGACY_TESTS=OFF -DCAPSTONE_BUILD_CSTOOL=OFF -G "NMake Makefiles" ..')
elif 'AFL_NOOPT' in os.environ:
# build for test_corpus
os.system('cmake -DBUILD_SHARED_LIBS=ON -DCAPSTONE_BUILD_LEGACY_TESTS=OFF -DCAPSTONE_BUILD_CSTOOL=OFF ..')
else:
os.system('cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCAPSTONE_BUILD_LEGACY_TESTS=OFF -DCAPSTONE_BUILD_CSTOOL=OFF -G "Unix Makefiles" ..')
os.system("cmake --build .")
shutil.copy(VERSIONED_LIBRARY_FILE, os.path.join(LIBS_DIR, LIBRARY_FILE))
@ -182,8 +180,6 @@ class custom_bdist_egg(bdist_egg):
self.run_command('build')
return bdist_egg.run(self)
def dummy_src():
return []
cmdclass = {}
cmdclass['build'] = custom_build
@ -192,6 +188,7 @@ cmdclass['bdist_egg'] = custom_bdist_egg
try:
from setuptools.command.develop import develop
class custom_develop(develop):
def run(self):
logger.info("Building C extensions")

View File

@ -1,193 +0,0 @@
#!/usr/bin/env python3
# Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
from capstone import *
from capstone.aarch64 import *
from xprint import to_hex, to_x, to_x_32
AArch64_CODE = b"\x09\x00\x38\xd5\xbf\x40\x00\xd5\x0c\x05\x13\xd5\x20\x50\x02\x0e\x20\xe4\x3d\x0f\x00\x18\xa0\x5f\xa2\x00\xae\x9e\x9f\x37\x03\xd5\xbf\x33\x03\xd5\xdf\x3f\x03\xd5\x21\x7c\x02\x9b\x21\x7c\x00\x53\x00\x40\x21\x4b\xe1\x0b\x40\xb9\x20\x04\x81\xda\x20\x08\x02\x8b\x10\x5b\xe8\x3c\xfd\x7b\xba\xa9\xfd\xc7\x43\xf8"
all_tests = (
(CS_ARCH_AARCH64, CS_MODE_ARM, AArch64_CODE, "AARCH64"),
)
def print_insn_detail(insn):
# print address, mnemonic and operands
print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
# "data" instruction generated by SKIPDATA option has no detail
if insn.id == 0:
return
if len(insn.operands) > 0:
print("\top_count: %u" % len(insn.operands))
c = -1
for i in insn.operands:
c += 1
if i.type == AARCH64_OP_REG:
print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
if i.type == AARCH64_OP_IMM:
print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x(i.imm)))
if i.type == AARCH64_OP_CIMM:
print("\t\toperands[%u].type: C-IMM = %u" % (c, i.imm))
if i.type == AARCH64_OP_FP:
print("\t\toperands[%u].type: FP = %f" % (c, i.fp))
if i.type == AARCH64_OP_MEM:
print("\t\toperands[%u].type: MEM" % c)
if i.mem.base != 0:
print("\t\t\toperands[%u].mem.base: REG = %s" \
% (c, insn.reg_name(i.mem.base)))
if i.mem.index != 0:
print("\t\t\toperands[%u].mem.index: REG = %s" \
% (c, insn.reg_name(i.mem.index)))
if i.mem.disp != 0:
print("\t\t\toperands[%u].mem.disp: 0x%s" \
% (c, to_x_32(i.mem.disp)))
if insn.post_index:
print("\t\t\tpost-indexed: true");
if i.type == AARCH64_OP_SME:
print("\t\toperands[%u].type: SME_MATRIX" % (c))
print("\t\toperands[%u].sme.type: %d" % (c, i.sme.type))
if i.sme.tile != AARCH64_REG_INVALID:
print("\t\toperands[%u].sme.tile: %s" % (c, insn.reg_name(i.sme.tile)))
if i.sme.slice_reg != AARCH64_REG_INVALID:
print("\t\toperands[%u].sme.slice_reg: %s" % (c, insn.reg_name(i.sme.slice_reg)))
if i.sme.slice_offset.imm != -1 or i.sme.slice_offset.imm_range.first != -1:
print("\t\toperands[%u].sme.slice_offset: " % (c))
if i.sme.has_range_offset:
print("%hhd:%hhd" % (i.sme.slice_offset.imm_range.first, i.sme.slice_offset.imm_range.offset))
else:
print("%d" % (i.sme.slice_offset.imm))
if i.sme.slice_reg != AARCH64_REG_INVALID or i.sme.slice_offset.imm != -1:
print("\t\toperands[%u].sme.is_vertical: %s" % (c, ("true" if i.sme.is_vertical else "false")))
if i.type == AARCH64_OP_PRED:
print("\t\toperands[%u].type: PREDICATE\n" % c);
if (op.pred.reg != AARCH64_REG_INVALID):
print("\t\toperands[%u].pred.reg: %s\n" % (c, insn.reg_name(i.pred.reg)));
if (op.pred.vec_select != AARCH64_REG_INVALID):
print("\t\toperands[%u].pred.vec_select: %s\n" % (c, insn.reg_name(i.pred.vec_select)));
if (op.pred.imm_index != -1):
print("\t\toperands[%u].pred.imm_index: %d\n" % (i, op.pred.imm_index));
break;
if i.type == AARCH64_OP_SYSREG:
print("\t\toperands[%u].type: SYS REG:" % (c))
if i.sysop.sub_type == AARCH64_OP_REG_MRS:
print("\t\toperands[%u].subtype: REG_MRS = 0x%x" % (c, i.sysop.reg.sysreg))
if i.sysop.sub_type == AARCH64_OP_REG_MSR:
print("\t\toperands[%u].subtype: REG_MSR = 0x%x" % (c, i.sysop.reg.sysreg))
if i.sysop.sub_type == AARCH64_OP_TLBI:
print("\t\toperands[%u].subtype TLBI = 0x%x" % (c, i.sysop.reg.tlbi))
if i.sysop.sub_type == AARCH64_OP_IC:
print("\t\toperands[%u].subtype IC = 0x%x" % (c, i.sysop.reg.ic))
if i.type == AARCH64_OP_SYSALIAS:
print("\t\toperands[%u].type: SYS ALIAS:" % (c))
if i.sysop.sub_type == AARCH64_OP_SVCR:
if i.sysop.alias.svcr == AARCH64_SVCR_SVCRSM:
print("\t\t\toperands[%u].svcr: BIT = SM" % (c))
elif i.sysop.alias.svcr == AARCH64_SVCR_SVCRZA:
print("\t\t\toperands[%u].svcr: BIT = ZA" % (c))
elif i.sysop.alias.svcr == AARCH64_SVCR_SVCRSMZA:
print("\t\t\toperands[%u].svcr: BIT = SM & ZA" % (c))
if i.sysop.sub_type == AARCH64_OP_AT:
print("\t\toperands[%u].subtype AT = 0x%x" % (c, i.sysop.alias.at))
if i.sysop.sub_type == AARCH64_OP_DB:
print("\t\toperands[%u].subtype DB = 0x%x" % (c, i.sysop.alias.db))
if i.sysop.sub_type == AARCH64_OP_DC:
print("\t\toperands[%u].subtype DC = 0x%x" % (c, i.sysop.alias.dc))
if i.sysop.sub_type == AARCH64_OP_ISB:
print("\t\toperands[%u].subtype ISB = 0x%x" % (c, i.sysop.alias.isb))
if i.sysop.sub_type == AARCH64_OP_TSB:
print("\t\toperands[%u].subtype TSB = 0x%x" % (c, i.sysop.alias.tsb))
if i.sysop.sub_type == AARCH64_OP_PRFM:
print("\t\toperands[%u].subtype PRFM = 0x%x" % (c, i.sysop.alias.prfm))
if i.sysop.sub_type == AARCH64_OP_SVEPRFM:
print("\t\toperands[%u].subtype SVEPRFM = 0x%x" % (c, i.sysop.alias.sveprfm))
if i.sysop.sub_type == AARCH64_OP_RPRFM:
print("\t\toperands[%u].subtype RPRFM = 0x%x" % (c, i.sysop.alias.rprfm))
if i.sysop.sub_type == AARCH64_OP_PSTATEIMM0_15:
print("\t\toperands[%u].subtype PSTATEIMM0_15 = 0x%x" % (c, i.sysop.alias.pstateimm0_15))
if i.sysop.sub_type == AARCH64_OP_PSTATEIMM0_1:
print("\t\toperands[%u].subtype PSTATEIMM0_1 = 0x%x" % (c, i.sysop.alias.pstateimm0_1))
if i.sysop.sub_type == AARCH64_OP_PSB:
print("\t\toperands[%u].subtype PSB = 0x%x" % (c, i.sysop.alias.psb))
if i.sysop.sub_type == AARCH64_OP_BTI:
print("\t\toperands[%u].subtype BTI = 0x%x" % (c, i.sysop.alias.bti))
if i.sysop.sub_type == AARCH64_OP_SVEPREDPAT:
print("\t\toperands[%u].subtype SVEPREDPAT = 0x%x" % (c, i.sysop.alias.svepredpat))
if i.sysop.sub_type == AARCH64_OP_SVEVECLENSPECIFIER:
print("\t\toperands[%u].subtype SVEVECLENSPECIFIER = 0x%x" % (c, i.sysop.alias.sveveclenspecifier))
if i.type == AARCH64_OP_SYSIMM:
print("\t\toperands[%u].type: SYS IMM:" % (c))
if i.sysop.sub_type == AARCH64_OP_EXACTFPIMM:
print("\t\toperands[%u].subtype EXACTFPIMM = %d" % (c, i.sysop.imm.exactfpimm))
if i.sysop.sub_type == AARCH64_OP_DBNXS:
print("\t\toperands[%u].subtype DBNXS = %d" % (c, i.sysop.imm.dbnxs))
if i.access == CS_AC_READ:
print("\t\toperands[%u].access: READ" % (c))
elif i.access == CS_AC_WRITE:
print("\t\toperands[%u].access: WRITE" % (c))
elif i.access == CS_AC_READ | CS_AC_WRITE:
print("\t\toperands[%u].access: READ | WRITE" % (c))
if i.shift.type != AARCH64_SFT_INVALID and i.shift.value:
print("\t\t\tShift: type = %u, value = %u" % (i.shift.type, i.shift.value))
if i.ext != AARCH64_EXT_INVALID:
print("\t\t\tExt: %u" % i.ext)
if i.vas != AARCH64LAYOUT_INVALID:
print("\t\t\tVector Arrangement Specifier: 0x%x" % i.vas)
if i.vector_index != -1:
print("\t\t\tVector Index: %u" % i.vector_index)
if insn.writeback:
print("\tWrite-back: True")
if insn.cc != AArch64CC_Invalid:
print("\tCode-condition: %u" % insn.cc)
if insn.update_flags:
print("\tUpdate-flags: True")
(regs_read, regs_write) = insn.regs_access()
if len(regs_read) > 0:
print("\tRegisters read:", end="")
for r in regs_read:
print(" %s" %(insn.reg_name(r)), end="")
print("")
if len(regs_write) > 0:
print("\tRegisters modified:", end="")
for r in regs_write:
print(" %s" %(insn.reg_name(r)), end="")
print("")
# ## Test class Cs
def test_class():
for (arch, mode, code, comment) in all_tests:
print("*" * 16)
print("Platform: %s" % comment)
print("Code: %s" % to_hex(code))
print("Disasm:")
try:
md = Cs(arch, mode)
md.detail = True
for insn in md.disasm(code, 0x2c):
print_insn_detail(insn)
print ()
print("0x%x:\n" % (insn.address + insn.size))
except CsError as e:
print("ERROR: %s" % e)
if __name__ == '__main__':
test_class()

View File

@ -1,26 +1,9 @@
#!/usr/bin/env python3
import test_basic, test_arm, test_aarch64, test_detail, test_lite, test_m68k, test_mips, \
test_ppc, test_x86, test_skipdata, test_sparc, test_systemz, test_tms320c64x, test_customized_mnem, \
test_m680x, test_mos65xx, test_xcore, test_riscv, test_alpha, test_hppa
import test_lite
import test_skipdata
import test_customized_mnem
test_basic.test_class()
test_arm.test_class()
test_aarch64.test_class()
test_detail.test_class()
test_lite.test_class()
test_m68k.test_class()
test_mips.test_class()
test_mos65xx.test_class()
test_ppc.test_class()
test_sparc.test_class()
test_systemz.test_class()
test_x86.test_class()
test_tms320c64x.test_class()
test_m680x.test_class()
test_skipdata.test_class()
test_customized_mnem.test()
test_xcore.test_class()
test_riscv.test_class()
test_alpha.test_class()
test_hppa.test_class()

View File

@ -1,57 +0,0 @@
#!/usr/bin/env python3
# Capstone Python bindings, by Dmitry Sibirtsev <sibirtsev_dl@gmail.com>
from capstone import *
from capstone.alpha import *
from xprint import to_x, to_hex
ALPHA_CODE = b'\x02\x00\xbb\x27\x50\x7a\xbd\x23\xd0\xff\xde\x23\x00\x00\x5e\xb7'
ALPHA_CODE_BE = b'\x27\xbb\x00\x02\x23\xbd\x7a\x50\x23\xde\xff\xd0\xb7\x5e\x00\x00'
all_tests = (
(CS_ARCH_ALPHA, CS_MODE_LITTLE_ENDIAN, ALPHA_CODE, "Alpha (Little-endian)"),
(CS_ARCH_ALPHA, CS_MODE_BIG_ENDIAN, ALPHA_CODE_BE, "Alpha (Big-endian)"),
)
def print_insn_detail(insn):
# print address, mnemonic and operands
print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
# "data" instruction generated by SKIPDATA option has no detail
if insn.id == 0:
return
if len(insn.operands) > 0:
print("\top_count: %u" % len(insn.operands))
c = 0
for i in insn.operands:
if i.type == ALPHA_OP_REG:
print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
if i.type == ALPHA_OP_IMM:
print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x(i.imm)))
c += 1
# ## Test class Cs
def test_class():
for (arch, mode, code, comment) in all_tests:
print("*" * 16)
print("Platform: %s" % comment)
print("Code: %s" % to_hex(code))
print("Disasm:")
try:
md = Cs(arch, mode)
md.detail = True
for insn in md.disasm(code, 0x1000):
print_insn_detail(insn)
print()
print("0x%x:\n" % (insn.address + insn.size))
except CsError as e:
print("ERROR: %s" % e)
if __name__ == '__main__':
test_class()

View File

@ -1,189 +0,0 @@
#!/usr/bin/env python3
# Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
from capstone import *
from capstone.arm import *
from xprint import to_hex, to_x_32
ARM_CODE = b"\x86\x48\x60\xf4\x4d\x0f\xe2\xf4\xED\xFF\xFF\xEB\x04\xe0\x2d\xe5\x00\x00\x00\x00\xe0\x83\x22\xe5\xf1\x02\x03\x0e\x00\x00\xa0\xe3\x02\x30\xc1\xe7\x00\x00\x53\xe3\x00\x02\x01\xf1\x05\x40\xd0\xe8\xf4\x80\x00\x00"
ARM_CODE2 = b"\xd1\xe8\x00\xf0\xf0\x24\x04\x07\x1f\x3c\xf2\xc0\x00\x00\x4f\xf0\x00\x01\x46\x6c"
THUMB_CODE = b"\x60\xf9\x1f\x04\xe0\xf9\x4f\x07\x70\x47\x00\xf0\x10\xe8\xeb\x46\x83\xb0\xc9\x68\x1f\xb1\x30\xbf\xaf\xf3\x20\x84\x52\xf8\x23\xf0"
THUMB_CODE2 = b"\x4f\xf0\x00\x01\xbd\xe8\x00\x88\xd1\xe8\x00\xf0\x18\xbf\xad\xbf\xf3\xff\x0b\x0c\x86\xf3\x00\x89\x80\xf3\x00\x8c\x4f\xfa\x99\xf6\xd0\xff\xa2\x01"
THUMB_MCLASS = b"\xef\xf3\x02\x80"
ARMV8 = b"\xe0\x3b\xb2\xee\x42\x00\x01\xe1\x51\xf0\x7f\xf5"
all_tests = (
(CS_ARCH_ARM, CS_MODE_ARM, ARM_CODE, "ARM", None),
(CS_ARCH_ARM, CS_MODE_THUMB, THUMB_CODE, "Thumb", None),
(CS_ARCH_ARM, CS_MODE_THUMB, ARM_CODE2, "Thumb-mixed", None),
(CS_ARCH_ARM, CS_MODE_THUMB, THUMB_CODE2, "Thumb-2 & register named with numbers", CS_OPT_SYNTAX_NOREGNAME),
(CS_ARCH_ARM, CS_MODE_THUMB + CS_MODE_MCLASS, THUMB_MCLASS, "Thumb-MClass", None),
(CS_ARCH_ARM, CS_MODE_ARM + CS_MODE_V8, ARMV8, "Arm-V8", None),
)
def print_insn_detail(insn):
# print address, mnemonic and operands
print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
# "data" instruction generated by SKIPDATA option has no detail
if insn.id == 0:
return
if len(insn.operands) > 0:
print("\top_count: %u" % len(insn.operands))
c = 0
for i in insn.operands:
if i.type == ARM_OP_REG:
print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
elif i.type == ARM_OP_IMM:
print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x_32(i.imm)))
elif i.type == ARM_OP_FP:
print("\t\toperands[%u].type: FP = %f" % (c, i.fp))
elif i.type == ARM_OP_PRED:
print("\t\toperands[%u].type: PRED = %d" % (c, i.pred))
elif i.type == ARM_OP_CIMM:
print("\t\toperands[%u].type: C-IMM = %u" % (c, i.imm))
elif i.type == ARM_OP_PIMM:
print("\t\toperands[%u].type: P-IMM = %u" % (c, i.imm))
elif i.type == ARM_OP_SETEND:
if i.setend == ARM_SETEND_BE:
print("\t\toperands[%u].type: SETEND = be" % c)
else:
print("\t\toperands[%u].type: SETEND = le" % c)
elif i.type == ARM_OP_MEM:
print("\t\toperands[%u].type: MEM" % c)
if i.mem.base != 0:
print("\t\t\toperands[%u].mem.base: REG = %s" \
% (c, insn.reg_name(i.mem.base)))
if i.mem.index != 0:
print("\t\t\toperands[%u].mem.index: REG = %s" \
% (c, insn.reg_name(i.mem.index)))
if i.mem.scale != 1:
print("\t\t\toperands[%u].mem.scale: %u" \
% (c, i.mem.scale))
if i.mem.disp != 0:
print("\t\t\toperands[%u].mem.disp: 0x%s" \
% (c, to_x_32(i.mem.disp)))
if i.mem.lshift != 0:
print("\t\t\toperands[%u].mem.lshift: 0x%s" \
% (c, to_x_32(i.mem.lshift)))
elif i.type == ARM_OP_SYSM:
print("\t\toperands[%u].type: SYSM = 0x%x" % (c, i.sysop.sysm))
print("\t\toperands[%u].type: MASK = %u" % (c, i.sysop.msr_mask))
elif i.type == ARM_OP_SYSREG:
print("\t\toperands[%u].type: SYSREG = %s" % (c, insn.reg_name(i.sysop.reg.mclasssysreg)))
print("\t\toperands[%u].type: MASK = %u" % (c, i.sysop.msr_mask))
elif i.type == ARM_OP_BANKEDREG:
print("\t\toperands[%u].type: BANKEDREG = %u" % (c, i.sysop.reg.bankedreg))
if i.sysop.msr_mask != 2 ** (ctypes.sizeof(ctypes.c_uint8) * 8) - 1:
print("\t\toperands[%u].type: MASK = %u" % (c, i.sysop.msr_mask))
elif i.type in [ARM_OP_SPSR, ARM_OP_CPSR]:
print("\t\toperands[%u].type: %sPSR = " % (c, "S" if i.type == ARM_OP_SPSR else "C"), end="")
field = i.sysop.psr_bits
if (field & ARM_FIELD_SPSR_F) > 0 or (field & ARM_FIELD_CPSR_F) > 0:
print("f", end="")
if (field & ARM_FIELD_SPSR_S) > 0 or (field & ARM_FIELD_CPSR_S) > 0:
print("s", end="")
if (field & ARM_FIELD_SPSR_X) > 0 or (field & ARM_FIELD_CPSR_X) > 0:
print("x", end="")
if (field & ARM_FIELD_SPSR_C) > 0 or (field & ARM_FIELD_CPSR_C) > 0:
print("c", end="")
print()
print("\t\toperands[%u].type: MASK = %u" % (c, i.sysop.msr_mask))
else:
print("\t\toperands[%u].type: UNKNOWN = %u" % (c, i.type))
if i.neon_lane != -1:
print("\t\toperands[%u].neon_lane = %u" % (c, i.neon_lane))
if i.access == CS_AC_READ:
print("\t\toperands[%u].access: READ" % (c))
elif i.access == CS_AC_WRITE:
print("\t\toperands[%u].access: WRITE" % (c))
elif i.access == CS_AC_READ | CS_AC_WRITE:
print("\t\toperands[%u].access: READ | WRITE" % (c))
if i.shift.type != ARM_SFT_INVALID and i.shift.value:
if i.shift.type < ARM_SFT_ASR_REG:
# shift with constant value
print("\t\t\tShift: %u = %u" \
% (i.shift.type, i.shift.value))
else:
# shift with register
print("\t\t\tShift: %u = %s" \
% (i.shift.type, insn.reg_name(i.shift.value)))
if i.vector_index != -1:
print("\t\t\toperands[%u].vector_index = %u" %(c, i.vector_index))
if i.subtracted:
print("\t\t\toperands[%u].subtracted = True" %c)
c += 1
if not insn.cc in [ARMCC_AL, ARMCC_UNDEF]:
print("\tCode condition: %u" % insn.cc)
if insn.vcc != ARMVCC_None:
print("\tVector code condition: %u" % insn.vcc)
if insn.update_flags:
print("\tUpdate-flags: True")
if insn.writeback:
if insn.post_index:
print("\tWrite-back: Post")
else:
print("\tWrite-back: Pre")
if insn.cps_mode:
print("\tCPSI-mode: %u" %(insn.cps_mode))
if insn.cps_flag:
print("\tCPSI-flag: %u" %(insn.cps_flag))
if insn.vector_data:
print("\tVector-data: %u" %(insn.vector_data))
if insn.vector_size:
print("\tVector-size: %u" %(insn.vector_size))
if insn.usermode:
print("\tUser-mode: True")
if insn.mem_barrier:
print("\tMemory-barrier: %u" %(insn.mem_barrier))
if insn.pred_mask:
print("\tPredicate Mask: 0x%x" %(insn.pred_mask))
(regs_read, regs_write) = insn.regs_access()
if len(regs_read) > 0:
print("\tRegisters read:", end="")
for r in regs_read:
print(" %s" %(insn.reg_name(r)), end="")
print("")
if len(regs_write) > 0:
print("\tRegisters modified:", end="")
for r in regs_write:
print(" %s" %(insn.reg_name(r)), end="")
print("")
# ## Test class Cs
def test_class():
for (arch, mode, code, comment, syntax) in all_tests:
print("*" * 16)
print("Platform: %s" % comment)
print("Code: %s" % to_hex(code))
print("Disasm:")
try:
md = Cs(arch, mode)
if syntax is not None:
md.syntax = syntax
md.detail = True
for insn in md.disasm(code, 0x80001000):
print_insn_detail(insn)
print ()
print("0x%x:\n" % (insn.address + insn.size))
except CsError as e:
print("ERROR: %s" % e)
if __name__ == '__main__':
test_class()

View File

@ -1,144 +0,0 @@
#!/usr/bin/env python3
# Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
from capstone import *
from xprint import to_hex
X86_CODE16 = b"\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00"
X86_CODE32 = b"\xba\xcd\xab\x00\x00\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00"
X86_CODE64 = b"\x55\x48\x8b\x05\xb8\x13\x00\x00"
ARM_CODE = b"\xED\xFF\xFF\xEB\x04\xe0\x2d\xe5\x00\x00\x00\x00\xe0\x83\x22\xe5\xf1\x02\x03\x0e\x00\x00\xa0\xe3\x02\x30\xc1\xe7\x00\x00\x53\xe3"
ARM_CODE2 = b"\x10\xf1\x10\xe7\x11\xf2\x31\xe7\xdc\xa1\x2e\xf3\xe8\x4e\x62\xf3"
THUMB_CODE = b"\x70\x47\xeb\x46\x83\xb0\xc9\x68"
THUMB_CODE2 = b"\x4f\xf0\x00\x01\xbd\xe8\x00\x88\xd1\xe8\x00\xf0"
THUMB_MCLASS = b"\xef\xf3\x02\x80"
ARMV8 = b"\xe0\x3b\xb2\xee\x42\x00\x01\xe1\x51\xf0\x7f\xf5"
MIPS_CODE = b"\x0C\x10\x00\x97\x00\x00\x00\x00\x24\x02\x00\x0c\x8f\xa2\x00\x00\x34\x21\x34\x56"
MIPS_CODE2 = b"\x56\x34\x21\x34\xc2\x17\x01\x00"
MIPS_32R6M = b"\x00\x07\x00\x07\x00\x11\x93\x7c\x01\x8c\x8b\x7c\x00\xc7\x48\xd0"
MIPS_32R6 = b"\xec\x80\x00\x19\x7c\x43\x22\xa0"
AARCH64_CODE = b"\x21\x7c\x02\x9b\x21\x7c\x00\x53\x00\x40\x21\x4b\xe1\x0b\x40\xb9"
PPC_CODE = b"\x80\x20\x00\x00\x80\x3f\x00\x00\x10\x43\x23\x0e\xd0\x44\x00\x80\x4c\x43\x22\x02\x2d\x03\x00\x80\x7c\x43\x20\x14\x7c\x43\x20\x93\x4f\x20\x00\x21\x4c\xc8\x00\x21"
PPC_CODE2 = b"\x10\x60\x2a\x10\x10\x64\x28\x88\x7c\x4a\x5d\x0f"
SPARC_CODE = b"\x80\xa0\x40\x02\x85\xc2\x60\x08\x85\xe8\x20\x01\x81\xe8\x00\x00\x90\x10\x20\x01\xd5\xf6\x10\x16\x21\x00\x00\x0a\x86\x00\x40\x02\x01\x00\x00\x00\x12\xbf\xff\xff\x10\xbf\xff\xff\xa0\x02\x00\x09\x0d\xbf\xff\xff\xd4\x20\x60\x00\xd4\x4e\x00\x16\x2a\xc2\x80\x03"
SPARCV9_CODE = b"\x81\xa8\x0a\x24\x89\xa0\x10\x20\x89\xa0\x1a\x60\x89\xa0\x00\xe0"
SYSZ_CODE = b"\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78"
XCORE_CODE = b"\xfe\x0f\xfe\x17\x13\x17\xc6\xfe\xec\x17\x97\xf8\xec\x4f\x1f\xfd\xec\x37\x07\xf2\x45\x5b\xf9\xfa\x02\x06\x1b\x10"
M68K_CODE = b"\xd4\x40\x87\x5a\x4e\x71\x02\xb4\xc0\xde\xc0\xde\x5c\x00\x1d\x80\x71\x12\x01\x23\xf2\x3c\x44\x22\x40\x49\x0e\x56\x54\xc5\xf2\x3c\x44\x00\x44\x7a\x00\x00\xf2\x00\x0a\x28\x4E\xB9\x00\x00\x00\x12\x4E\x75"
TMS320C64X_CODE = b"\x01\xac\x88\x40\x81\xac\x88\x43\x00\x00\x00\x00\x02\x90\x32\x96\x02\x80\x46\x9e\x05\x3c\x83\xe6\x0b\x0c\x8b\x24"
M680X_CODE = b"\x06\x10\x19\x1a\x55\x1e\x01\x23\xe9\x31\x06\x34\x55\xa6\x81\xa7\x89\x7f\xff\xa6\x9d\x10\x00\xa7\x91\xa6\x9f\x10\x00\x11\xac\x99\x10\x00\x39"
EVM_CODE = b"\x60\x61"
WASM_CODE = b"\x20\x00\x20\x01\x41\x20\x10\xc9\x01\x45\x0b"
MOS65XX_CODE = b"\x0d\x34\x12\x00\x81\x65\x6c\x01\x00\x85\xFF\x10\x00\x19\x42\x42\x00\x49\x42"
EBPF_CODE = b"\x97\x09\x00\x00\x37\x13\x03\x00\xdc\x02\x00\x00\x20\x00\x00\x00\x30\x00\x00\x00\x00\x00\x00\x00\xdb\x3a\x00\x01\x00\x00\x00\x00\x84\x02\x00\x00\x00\x00\x00\x00\x6d\x33\x17\x02\x00\x00\x00\x00"
RISCV_CODE32 = b"\x37\x34\x00\x00\x97\x82\x00\x00\xef\x00\x80\x00\xef\xf0\x1f\xff\xe7\x00\x45\x00\xe7\x00\xc0\xff\x63\x05\x41\x00\xe3\x9d\x61\xfe\x63\xca\x93\x00\x63\x53\xb5\x00\x63\x65\xd6\x00\x63\x76\xf7\x00\x03\x88\x18\x00\x03\x99\x49\x00\x03\xaa\x6a\x00\x03\xcb\x2b\x01\x03\xdc\x8c\x01\x23\x86\xad\x03\x23\x9a\xce\x03\x23\x8f\xef\x01\x93\x00\xe0\x00\x13\xa1\x01\x01\x13\xb2\x02\x7d\x13\xc3\x03\xdd\x13\xe4\xc4\x12\x13\xf5\x85\x0c\x13\x96\xe6\x01\x13\xd7\x97\x01\x13\xd8\xf8\x40\x33\x89\x49\x01\xb3\x0a\x7b\x41\x33\xac\xac\x01\xb3\x3d\xde\x01\x33\xd2\x62\x40\xb3\x43\x94\x00\x33\xe5\xc5\x00\xb3\x76\xf7\x00\xb3\x54\x39\x01\xb3\x50\x31\x00\x33\x9f\x0f\x00"
RISCV_CODE64 = b"\x13\x04\xa8\x7a"
ALPHA_CODE = b'\x02\x00\xbb\x27\x50\x7a\xbd\x23\xd0\xff\xde\x23\x00\x00\x5e\xb7'
ALPHA_CODE_BE = b'\x27\xbb\x00\x02\x23\xbd\x7a\x50\x23\xde\xff\xd0\xb7\x5e\x00\x00'
HPPA_20_CODE_BE = b'\x00\x20\x50\xa2\x00\x01\x58\x20\x00\x00\x44\xa1\x00\x41\x18\x40\x00\x20\x08\xa2\x01\x60\x48\xa1\x01\x61\x18\xc0\x00\x00\x14\xa1\x00\x0f\x0d\x61\x00\x0f\x0e\x61\x00\x01\x18\x60\x00\x00\x0c\x00\x00\x00\x0c\xa0\x03\xff\xc0\x1f\x00\x00\x04\x00\x00\x10\x04\x00\x04\x22\x51\x83\x04\x22\x51\xc3\x04\x22\x51\x83\x04\x2f\x71\x83\x04\x2f\x71\xc3\x04\x2f\x71\x83\x04\x41\x53\x43\x04\x41\x53\x63\x04\x41\x53\x03\x04\x41\x12\x00\x04\x41\x16\x00\x04\x41\x16\x20\x04\x41\x42\x00\x04\x41\x46\x00\x04\x41\x46\x20\x04\x41\x12\x40\x04\x41\x12\x60\x04\x41\x42\x40\x04\x41\x42\x60\x04\x41\x18\x00\x04\x41\x08\x00\x04\x41\x13\x80\x04\x41\x13\xa0\x04\x41\x52\x80\x04\x41\x52\xa0\x04\x5e\x72\x80\x04\x41\x42\x80\x04\x41\x52\xc0\x04\x41\x52\xe0\x04\x41\x42\xc0\x04\x41\x42\xe0\x14\x00\xde\xad'
HPPA_20_CODE = b'\xa2\x50\x20\x00\x20\x58\x01\x00\xa1\x44\x00\x00\x40\x18\x41\x00\xa2\x08\x20\x00\xa1\x48\x60\x01\xc0\x18\x61\x01\xa1\x14\x00\x00\x61\x0d\x0f\x00\x61\x0e\x0f\x00\x60\x18\x01\x00\x00\x0c\x00\x00\xa0\x0c\x00\x00\x1f\xc0\xff\x03\x00\x04\x00\x00\x00\x04\x10\x00\x83\x51\x22\x04\xc3\x51\x22\x04\x83\x51\x22\x04\x83\x71\x2f\x04\xc3\x71\x2f\x04\x83\x71\x2f\x04\x43\x53\x41\x04\x63\x53\x41\x04\x03\x53\x41\x04\x00\x12\x41\x04\x00\x16\x41\x04\x20\x16\x41\x04\x00\x42\x41\x04\x00\x46\x41\x04\x20\x46\x41\x04\x40\x12\x41\x04\x60\x12\x41\x04\x40\x42\x41\x04\x60\x42\x41\x04\x00\x18\x41\x04\x00\x08\x41\x04\x80\x13\x41\x04\xa0\x13\x41\x04\x80\x52\x41\x04\xa0\x52\x41\x04\x80\x72\x5e\x04\x80\x42\x41\x04\xc0\x52\x41\x04\xe0\x52\x41\x04\xc0\x42\x41\x04\xe0\x42\x41\x04\xad\xde\x00\x14'
HPPA_11_CODE_BE = b'\x24\x41\x40\xc3\x24\x41\x60\xc3\x24\x41\x40\xe3\x24\x41\x60\xe3\x24\x41\x68\xe3\x2c\x41\x40\xc3\x2c\x41\x60\xc3\x2c\x41\x40\xe3\x2c\x41\x60\xe3\x2c\x41\x68\xe3\x24\x62\x42\xc1\x24\x62\x62\xc1\x24\x62\x42\xe1\x24\x62\x46\xe1\x24\x62\x62\xe1\x24\x62\x6a\xe1\x2c\x62\x42\xc1\x2c\x62\x62\xc1\x2c\x62\x42\xe1\x2c\x62\x46\xe1\x2c\x62\x62\xe1\x2c\x62\x6a\xe1\x24\x3e\x50\xc2\x24\x3e\x50\xe2\x24\x3e\x70\xe2\x24\x3e\x78\xe2\x2c\x3e\x50\xc2\x2c\x3e\x50\xe2\x2c\x3e\x70\xe2\x2c\x3e\x78\xe2\x24\x5e\x52\xc1\x24\x5e\x52\xe1\x24\x5e\x56\xe1\x24\x5e\x72\xe1\x24\x5e\x7a\xe1\x2c\x5e\x52\xc1\x2c\x5e\x52\xe1\x2c\x5e\x56\xe1\x2c\x5e\x72\xe1\x2c\x5e\x7a\xe1'
HPPA_11_CODE = b'\xc3\x40\x41\x24\xc3\x60\x41\x24\xe3\x40\x41\x24\xe3\x60\x41\x24\xe3\x68\x41\x24\xc3\x40\x41\x2c\xc3\x60\x41\x2c\xe3\x40\x41\x2c\xe3\x60\x41\x2c\xe3\x68\x41\x2c\xc1\x42\x62\x24\xc1\x62\x62\x24\xe1\x42\x62\x24\xe1\x46\x62\x24\xe1\x62\x62\x24\xe1\x6a\x62\x24\xc1\x42\x62\x2c\xc1\x62\x62\x2c\xe1\x42\x62\x2c\xe1\x46\x62\x2c\xe1\x62\x62\x2c\xe1\x6a\x62\x2c\xc2\x50\x3e\x24\xe2\x50\x3e\x24\xe2\x70\x3e\x24\xe2\x78\x3e\x24\xc2\x50\x3e\x2c\xe2\x50\x3e\x2c\xe2\x70\x3e\x2c\xe2\x78\x3e\x2c\xc1\x52\x5e\x24\xe1\x52\x5e\x24\xe1\x56\x5e\x24\xe1\x72\x5e\x24\xe1\x7a\x5e\x24\xc1\x52\x5e\x2c\xe1\x52\x5e\x2c\xe1\x56\x5e\x2c\xe1\x72\x5e\x2c\xe1\x7a\x5e\x2c'
all_tests = (
(CS_ARCH_X86, CS_MODE_16, X86_CODE16, "X86 16bit (Intel syntax)", None),
(CS_ARCH_X86, CS_MODE_32, X86_CODE32, "X86 32bit (ATT syntax)", CS_OPT_SYNTAX_ATT),
(CS_ARCH_X86, CS_MODE_32, X86_CODE32, "X86 32 (Intel syntax)", None),
(CS_ARCH_X86, CS_MODE_32, X86_CODE32, "X86 32 (MASM syntax)", CS_OPT_SYNTAX_MASM),
(CS_ARCH_X86, CS_MODE_64, X86_CODE64, "X86 64 (Intel syntax)", None),
(CS_ARCH_ARM, CS_MODE_ARM, ARM_CODE, "ARM", None),
(CS_ARCH_ARM, CS_MODE_THUMB, THUMB_CODE2, "THUMB-2", None),
(CS_ARCH_ARM, CS_MODE_ARM, ARM_CODE2, "ARM: Cortex-A15 + NEON", None),
(CS_ARCH_ARM, CS_MODE_THUMB, THUMB_CODE, "THUMB", None),
(CS_ARCH_ARM, CS_MODE_THUMB + CS_MODE_MCLASS, THUMB_MCLASS, "Thumb-MClass", None),
(CS_ARCH_ARM, CS_MODE_ARM + CS_MODE_V8, ARMV8, "Arm-V8", None),
(CS_ARCH_MIPS, CS_MODE_MIPS32 + CS_MODE_BIG_ENDIAN, MIPS_CODE, "MIPS-32 (Big-endian)", None),
(CS_ARCH_MIPS, CS_MODE_MIPS64 + CS_MODE_LITTLE_ENDIAN, MIPS_CODE2, "MIPS-64-EL (Little-endian)", None),
(CS_ARCH_MIPS, CS_MODE_MIPS32R6 + CS_MODE_MICRO + CS_MODE_BIG_ENDIAN, MIPS_32R6M, "MIPS-32R6 | Micro (Big-endian)", None),
(CS_ARCH_MIPS, CS_MODE_MIPS32R6 + CS_MODE_BIG_ENDIAN, MIPS_32R6, "MIPS-32R6 (Big-endian)", None),
(CS_ARCH_AARCH64, CS_MODE_ARM, AARCH64_CODE, "AARCH64", None),
(CS_ARCH_PPC, CS_MODE_BIG_ENDIAN, PPC_CODE, "PPC-64", None),
(CS_ARCH_PPC, CS_MODE_BIG_ENDIAN, PPC_CODE, "PPC-64, print register with number only", CS_OPT_SYNTAX_NOREGNAME),
(CS_ARCH_PPC, CS_MODE_BIG_ENDIAN + CS_MODE_QPX, PPC_CODE2, "PPC-64 + QPX", None),
(CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN, SPARC_CODE, "Sparc", None),
(CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN + CS_MODE_V9, SPARCV9_CODE, "SparcV9", None),
(CS_ARCH_SYSZ, 0, SYSZ_CODE, "SystemZ", None),
(CS_ARCH_XCORE, 0, XCORE_CODE, "XCore", None),
(CS_ARCH_M68K, CS_MODE_BIG_ENDIAN | CS_MODE_M68K_040, M68K_CODE, "M68K", None),
(CS_ARCH_TMS320C64X, 0, TMS320C64X_CODE, "TMS320C64x", None),
(CS_ARCH_M680X, CS_MODE_M680X_6809, M680X_CODE, "M680X_M6809", None),
(CS_ARCH_EVM, 0, EVM_CODE, "EVM", None),
(CS_ARCH_WASM, 0, WASM_CODE, "WASM", None),
(CS_ARCH_MOS65XX, 0, MOS65XX_CODE, "MOS65XX", None),
(CS_ARCH_BPF, CS_MODE_LITTLE_ENDIAN | CS_MODE_BPF_EXTENDED, EBPF_CODE, "eBPF", None),
(CS_ARCH_RISCV, CS_MODE_RISCV32, RISCV_CODE32, "RISCV32", None),
(CS_ARCH_RISCV, CS_MODE_RISCV64, RISCV_CODE64, "RISCV64", None),
(CS_ARCH_ALPHA, CS_MODE_LITTLE_ENDIAN, ALPHA_CODE, "Alpha (Little-endian)", None),
(CS_ARCH_ALPHA, CS_MODE_BIG_ENDIAN, ALPHA_CODE_BE, "Alpha (Big-endian)", None),
(CS_ARCH_HPPA, CS_MODE_BIG_ENDIAN | CS_MODE_HPPA_20, HPPA_20_CODE_BE, "HPPA 2.0 (Big-endian)", None),
(CS_ARCH_HPPA, CS_MODE_LITTLE_ENDIAN | CS_MODE_HPPA_20, HPPA_20_CODE, "HPPA 2.0 (Little-endian)", None),
(CS_ARCH_HPPA, CS_MODE_BIG_ENDIAN | CS_MODE_HPPA_11, HPPA_11_CODE_BE, "HPPA 1.1 (Big-endian)", None),
(CS_ARCH_HPPA, CS_MODE_LITTLE_ENDIAN | CS_MODE_HPPA_11, HPPA_11_CODE, "HPPA 1.1 (Little-endian)", None),
)
# ## Test cs_disasm_quick()
def test_cs_disasm_quick():
for arch, mode, code, comment, syntax in all_tests:
print('*' * 40)
print("Platform: %s" % comment)
print("Disasm:")
print(to_hex(code))
for insn in cs_disasm_quick(arch, mode, code, 0x1000):
print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
print()
def test_different_data_formats():
data = bytes.fromhex('4831C948F7E1043B48BB0A2F62696E2F2F736852530A545F5257545E0F05')
mnemonics = ['xor', 'mul', 'add', 'movabs', 'push', 'pop', 'push', 'push', 'push', 'pop', 'syscall']
disassembler = Cs(CS_ARCH_X86, CS_MODE_64)
for name, code in (
('bytearray', bytearray(data)),
('memoryview of bytearray', memoryview(bytearray(data))),
('memoryview of data', memoryview(data)),
('raw data', data)
):
if mnemonics != [op for _, _, op, _ in disassembler.disasm_lite(code, 0)]:
print('failure in disassemble-lite for %s.' % name)
if mnemonics != [instruction.mnemonic for instruction in disassembler.disasm(code, 0)]:
print('failure in disassemble-full for %s.' % name)
# ## Test class Cs
def test_class():
for arch, mode, code, comment, syntax in all_tests:
print('*' * 16)
print("Platform: %s" % comment)
print("Code: %s" % to_hex(code))
print("Disasm:")
try:
md = Cs(arch, mode)
if syntax is not None:
md.syntax = syntax
for insn in md.disasm(code, 0x1000):
# bytes = binascii.hexlify(insn.bytes)
# print("0x%x:\t%s\t%s\t// hex-code: %s" %(insn.address, insn.mnemonic, insn.op_str, bytes))
print("0x%x:\t%s\t\t%s" % (insn.address, insn.mnemonic, insn.op_str))
print("0x%x:" % (insn.address + insn.size))
print()
except CsError as e:
print("ERROR: %s" % e)
# test_cs_disasm_quick()
# print ("*" * 40)
if __name__ == '__main__':
test_class()
test_different_data_formats()

View File

@ -1,91 +0,0 @@
#!/usr/bin/env python3
# Capstone Python bindings
# BPF tests by david942j <david942j@gmail.com>, 2019
from capstone import *
from capstone.bpf import *
from xprint import to_hex, to_x, to_x_32
CBPF_CODE = b"\x94\x09\x00\x00\x37\x13\x03\x00\x87\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x16\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00"
EBPF_CODE = b"\x97\x09\x00\x00\x37\x13\x03\x00\xdc\x02\x00\x00\x20\x00\x00\x00\x30\x00\x00\x00\x00\x00\x00\x00\xdb\x3a\x00\x01\x00\x00\x00\x00\x84\x02\x00\x00\x00\x00\x00\x00\x6d\x33\x17\x02\x00\x00\x00\x00"
all_tests = (
(CS_ARCH_BPF, CS_MODE_LITTLE_ENDIAN | CS_MODE_BPF_CLASSIC, CBPF_CODE, "cBPF Le", None),
(CS_ARCH_BPF, CS_MODE_LITTLE_ENDIAN | CS_MODE_BPF_EXTENDED, EBPF_CODE, "eBPF Le", None),
)
ext_name = {}
ext_name[BPF_EXT_LEN] = '#len'
def print_insn_detail(insn):
# print address, mnemonic and operands
print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
# "data" instruction generated by SKIPDATA option has no detail
if insn.id == 0:
return
if len(insn.groups) > 0:
print('\tGroups: ' + ' '.join(map(lambda g: insn.group_name(g), insn.groups)))
print("\tOperand count: %u" % len(insn.operands))
for c, op in enumerate(insn.operands):
print("\t\toperands[%u].type: " % c, end='')
if op.type == BPF_OP_REG:
print("REG = " + insn.reg_name(op.reg))
elif op.type == BPF_OP_IMM:
print("IMM = 0x" + to_x(op.imm))
elif op.type == BPF_OP_OFF:
print("OFF = +0x" + to_x_32(op.off))
elif op.type == BPF_OP_MEM:
print("MEM")
if op.mem.base != 0:
print("\t\t\toperands[%u].mem.base: REG = %s" \
% (c, insn.reg_name(op.mem.base)))
print("\t\t\toperands[%u].mem.disp: 0x%s" \
% (c, to_x_32(op.mem.disp)))
elif op.type == BPF_OP_MMEM:
print("MMEM = 0x" + to_x_32(op.mmem))
elif op.type == BPF_OP_MSH:
print("MSH = 4*([0x%s]&0xf)" % to_x_32(op.msh))
elif op.type == BPF_OP_EXT:
print("EXT = " + ext_name[op.ext])
(regs_read, regs_write) = insn.regs_access()
if len(regs_read) > 0:
print("\tRegisters read:", end="")
for r in regs_read:
print(" %s" % insn.reg_name(r), end="")
print("")
if len(regs_write) > 0:
print("\tRegisters modified:", end="")
for r in regs_write:
print(" %s" % insn.reg_name(r), end="")
print("")
def test_class():
for (arch, mode, code, comment, syntax) in all_tests:
print("*" * 16)
print("Platform: %s" % comment)
print("Code: %s" % to_hex(code))
print("Disasm:")
try:
md = Cs(arch, mode)
if syntax is not None:
md.syntax = syntax
md.detail = True
for insn in md.disasm(code, 0x0):
print_insn_detail(insn)
print ()
except CsError as e:
print("ERROR: %s" % e)
if __name__ == '__main__':
test_class()

View File

@ -1,126 +0,0 @@
#!/usr/bin/env python3
# Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
from capstone import *
from xprint import to_hex
X86_CODE16 = b"\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00"
X86_CODE32 = b"\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00"
X86_CODE64 = b"\x55\x48\x8b\x05\xb8\x13\x00\x00"
ARM_CODE = b"\xED\xFF\xFF\xEB\x04\xe0\x2d\xe5\x00\x00\x00\x00\xe0\x83\x22\xe5\xf1\x02\x03\x0e\x00\x00\xa0\xe3\x02\x30\xc1\xe7\x00\x00\x53\xe3"
ARM_CODE2 = b"\x10\xf1\x10\xe7\x11\xf2\x31\xe7\xdc\xa1\x2e\xf3\xe8\x4e\x62\xf3"
THUMB_CODE = b"\x70\x47\xeb\x46\x83\xb0\xc9\x68"
THUMB_CODE2 = b"\x4f\xf0\x00\x01\xbd\xe8\x00\x88\xd1\xe8\x00\xf0"
THUMB_MCLASS = b"\xef\xf3\x02\x80"
ARMV8 = b"\xe0\x3b\xb2\xee\x42\x00\x01\xe1\x51\xf0\x7f\xf5"
MIPS_CODE = b"\x0C\x10\x00\x97\x00\x00\x00\x00\x24\x02\x00\x0c\x8f\xa2\x00\x00\x34\x21\x34\x56\x00\x80\x04\x08"
MIPS_CODE2 = b"\x56\x34\x21\x34\xc2\x17\x01\x00"
MIPS_32R6M = b"\x00\x07\x00\x07\x00\x11\x93\x7c\x01\x8c\x8b\x7c\x00\xc7\x48\xd0"
MIPS_32R6 = b"\xec\x80\x00\x19\x7c\x43\x22\xa0"
AARCH64_CODE = b"\x09\x00\x38\xd5\xbf\x40\x00\xd5\x0c\x05\x13\xd5\x20\x50\x02\x0e\x20\xe4\x3d\x0f\x00\x18\xa0\x5f\xa2\x00\xae\x9e\x9f\x37\x03\xd5\xbf\x33\x03\xd5\xdf\x3f\x03\xd5\x21\x7c\x02\x9b\x21\x7c\x00\x53\x00\x40\x21\x4b\xe1\x0b\x40\xb9\x20\x04\x81\xda\x20\x08\x02\x8b\x10\x5b\xe8\x3c"
PPC_CODE = b"\x80\x20\x00\x00\x80\x3f\x00\x00\x10\x43\x23\x0e\xd0\x44\x00\x80\x4c\x43\x22\x02\x2d\x03\x00\x80\x7c\x43\x20\x14\x7c\x43\x20\x93\x4f\x20\x00\x21\x4c\xc8\x00\x21\x40\x82\x00\x14"
PPC_CODE2 = b"\x10\x60\x2a\x10\x10\x64\x28\x88\x7c\x4a\x5d\x0f"
SPARC_CODE = b"\x80\xa0\x40\x02\x85\xc2\x60\x08\x85\xe8\x20\x01\x81\xe8\x00\x00\x90\x10\x20\x01\xd5\xf6\x10\x16\x21\x00\x00\x0a\x86\x00\x40\x02\x01\x00\x00\x00\x12\xbf\xff\xff\x10\xbf\xff\xff\xa0\x02\x00\x09\x0d\xbf\xff\xff\xd4\x20\x60\x00\xd4\x4e\x00\x16\x2a\xc2\x80\x03"
SPARCV9_CODE = b"\x81\xa8\x0a\x24\x89\xa0\x10\x20\x89\xa0\x1a\x60\x89\xa0\x00\xe0"
SYSZ_CODE = b"\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78"
XCORE_CODE = b"\xfe\x0f\xfe\x17\x13\x17\xc6\xfe\xec\x17\x97\xf8\xec\x4f\x1f\xfd\xec\x37\x07\xf2\x45\x5b\xf9\xfa\x02\x06\x1b\x10"
M68K_CODE = b"\xd4\x40\x87\x5a\x4e\x71\x02\xb4\xc0\xde\xc0\xde\x5c\x00\x1d\x80\x71\x12\x01\x23\xf2\x3c\x44\x22\x40\x49\x0e\x56\x54\xc5\xf2\x3c\x44\x00\x44\x7a\x00\x00\xf2\x00\x0a\x28\x4E\xB9\x00\x00\x00\x12\x4E\x75"
M680X_CODE = b"\x06\x10\x19\x1a\x55\x1e\x01\x23\xe9\x31\x06\x34\x55\xa6\x81\xa7\x89\x7f\xff\xa6\x9d\x10\x00\xa7\x91\xa6\x9f\x10\x00\x11\xac\x99\x10\x00\x39"
MOS65XX_CODE = b"\x0A\x00\xFE\x34\x12\xD0\xFF\xEA\x19\x56\x34\x46\x80"
EBPF_CODE = b"\x97\x09\x00\x00\x37\x13\x03\x00\xdc\x02\x00\x00\x20\x00\x00\x00\x30\x00\x00\x00\x00\x00\x00\x00\xdb\x3a\x00\x01\x00\x00\x00\x00\x84\x02\x00\x00\x00\x00\x00\x00\x6d\x33\x17\x02\x00\x00\x00\x00"
ALPHA_CODE = b'\x02\x00\xbb\x27\x50\x7a\xbd\x23\xd0\xff\xde\x23\x00\x00\x5e\xb7'
ALPHA_CODE_BE = b'\x27\xbb\x00\x02\x23\xbd\x7a\x50\x23\xde\xff\xd0\xb7\x5e\x00\x00'
HPPA_20_CODE_BE = b'\x00\x20\x50\xa2\x00\x01\x58\x20\x00\x00\x44\xa1\x00\x41\x18\x40\x00\x20\x08\xa2\x01\x60\x48\xa1\x01\x61\x18\xc0\x00\x00\x14\xa1\x00\x0f\x0d\x61\x00\x0f\x0e\x61\x00\x01\x18\x60\x00\x00\x0c\x00\x00\x00\x0c\xa0\x03\xff\xc0\x1f\x00\x00\x04\x00\x00\x10\x04\x00\x04\x22\x51\x83\x04\x22\x51\xc3\x04\x22\x51\x83\x04\x2f\x71\x83\x04\x2f\x71\xc3\x04\x2f\x71\x83\x04\x41\x53\x43\x04\x41\x53\x63\x04\x41\x53\x03\x04\x41\x12\x00\x04\x41\x16\x00\x04\x41\x16\x20\x04\x41\x42\x00\x04\x41\x46\x00\x04\x41\x46\x20\x04\x41\x12\x40\x04\x41\x12\x60\x04\x41\x42\x40\x04\x41\x42\x60\x04\x41\x18\x00\x04\x41\x08\x00\x04\x41\x13\x80\x04\x41\x13\xa0\x04\x41\x52\x80\x04\x41\x52\xa0\x04\x5e\x72\x80\x04\x41\x42\x80\x04\x41\x52\xc0\x04\x41\x52\xe0\x04\x41\x42\xc0\x04\x41\x42\xe0\x14\x00\xde\xad'
HPPA_20_CODE = b'\xa2\x50\x20\x00\x20\x58\x01\x00\xa1\x44\x00\x00\x40\x18\x41\x00\xa2\x08\x20\x00\xa1\x48\x60\x01\xc0\x18\x61\x01\xa1\x14\x00\x00\x61\x0d\x0f\x00\x61\x0e\x0f\x00\x60\x18\x01\x00\x00\x0c\x00\x00\xa0\x0c\x00\x00\x1f\xc0\xff\x03\x00\x04\x00\x00\x00\x04\x10\x00\x83\x51\x22\x04\xc3\x51\x22\x04\x83\x51\x22\x04\x83\x71\x2f\x04\xc3\x71\x2f\x04\x83\x71\x2f\x04\x43\x53\x41\x04\x63\x53\x41\x04\x03\x53\x41\x04\x00\x12\x41\x04\x00\x16\x41\x04\x20\x16\x41\x04\x00\x42\x41\x04\x00\x46\x41\x04\x20\x46\x41\x04\x40\x12\x41\x04\x60\x12\x41\x04\x40\x42\x41\x04\x60\x42\x41\x04\x00\x18\x41\x04\x00\x08\x41\x04\x80\x13\x41\x04\xa0\x13\x41\x04\x80\x52\x41\x04\xa0\x52\x41\x04\x80\x72\x5e\x04\x80\x42\x41\x04\xc0\x52\x41\x04\xe0\x52\x41\x04\xc0\x42\x41\x04\xe0\x42\x41\x04\xad\xde\x00\x14'
HPPA_11_CODE_BE = b'\x24\x41\x40\xc3\x24\x41\x60\xc3\x24\x41\x40\xe3\x24\x41\x60\xe3\x24\x41\x68\xe3\x2c\x41\x40\xc3\x2c\x41\x60\xc3\x2c\x41\x40\xe3\x2c\x41\x60\xe3\x2c\x41\x68\xe3\x24\x62\x42\xc1\x24\x62\x62\xc1\x24\x62\x42\xe1\x24\x62\x46\xe1\x24\x62\x62\xe1\x24\x62\x6a\xe1\x2c\x62\x42\xc1\x2c\x62\x62\xc1\x2c\x62\x42\xe1\x2c\x62\x46\xe1\x2c\x62\x62\xe1\x2c\x62\x6a\xe1\x24\x3e\x50\xc2\x24\x3e\x50\xe2\x24\x3e\x70\xe2\x24\x3e\x78\xe2\x2c\x3e\x50\xc2\x2c\x3e\x50\xe2\x2c\x3e\x70\xe2\x2c\x3e\x78\xe2\x24\x5e\x52\xc1\x24\x5e\x52\xe1\x24\x5e\x56\xe1\x24\x5e\x72\xe1\x24\x5e\x7a\xe1\x2c\x5e\x52\xc1\x2c\x5e\x52\xe1\x2c\x5e\x56\xe1\x2c\x5e\x72\xe1\x2c\x5e\x7a\xe1'
HPPA_11_CODE = b'\xc3\x40\x41\x24\xc3\x60\x41\x24\xe3\x40\x41\x24\xe3\x60\x41\x24\xe3\x68\x41\x24\xc3\x40\x41\x2c\xc3\x60\x41\x2c\xe3\x40\x41\x2c\xe3\x60\x41\x2c\xe3\x68\x41\x2c\xc1\x42\x62\x24\xc1\x62\x62\x24\xe1\x42\x62\x24\xe1\x46\x62\x24\xe1\x62\x62\x24\xe1\x6a\x62\x24\xc1\x42\x62\x2c\xc1\x62\x62\x2c\xe1\x42\x62\x2c\xe1\x46\x62\x2c\xe1\x62\x62\x2c\xe1\x6a\x62\x2c\xc2\x50\x3e\x24\xe2\x50\x3e\x24\xe2\x70\x3e\x24\xe2\x78\x3e\x24\xc2\x50\x3e\x2c\xe2\x50\x3e\x2c\xe2\x70\x3e\x2c\xe2\x78\x3e\x2c\xc1\x52\x5e\x24\xe1\x52\x5e\x24\xe1\x56\x5e\x24\xe1\x72\x5e\x24\xe1\x7a\x5e\x24\xc1\x52\x5e\x2c\xe1\x52\x5e\x2c\xe1\x56\x5e\x2c\xe1\x72\x5e\x2c\xe1\x7a\x5e\x2c'
all_tests = (
(CS_ARCH_X86, CS_MODE_16, X86_CODE16, "X86 16bit (Intel syntax)", None),
(CS_ARCH_X86, CS_MODE_32, X86_CODE32, "X86 32bit (ATT syntax)", CS_OPT_SYNTAX_ATT),
(CS_ARCH_X86, CS_MODE_32, X86_CODE32, "X86 32 (Intel syntax)", None),
(CS_ARCH_X86, CS_MODE_64, X86_CODE64, "X86 64 (Intel syntax)", None),
(CS_ARCH_ARM, CS_MODE_ARM, ARM_CODE, "ARM", None),
(CS_ARCH_ARM, CS_MODE_ARM, ARM_CODE2, "ARM: Cortex-A15 + NEON", None),
(CS_ARCH_ARM, CS_MODE_THUMB, THUMB_CODE, "THUMB", None),
(CS_ARCH_ARM, CS_MODE_THUMB, THUMB_CODE2, "THUMB-2", None),
(CS_ARCH_ARM, CS_MODE_THUMB + CS_MODE_MCLASS, THUMB_MCLASS, "Thumb-MClass", None),
(CS_ARCH_ARM, CS_MODE_ARM + CS_MODE_V8, ARMV8, "Arm-V8", None),
(CS_ARCH_AARCH64, CS_MODE_ARM, AARCH64_CODE, "AARCH64", None),
(CS_ARCH_MIPS, CS_MODE_MIPS32 + CS_MODE_BIG_ENDIAN, MIPS_CODE, "MIPS-32 (Big-endian)", None),
(CS_ARCH_MIPS, CS_MODE_MIPS64 + CS_MODE_LITTLE_ENDIAN, MIPS_CODE2, "MIPS-64-EL (Little-endian)", None),
(CS_ARCH_MIPS, CS_MODE_MIPS32R6 + CS_MODE_MICRO + CS_MODE_BIG_ENDIAN, MIPS_32R6M, "MIPS-32R6 | Micro (Big-endian)", None),
(CS_ARCH_MIPS, CS_MODE_MIPS32R6 + CS_MODE_BIG_ENDIAN, MIPS_32R6, "MIPS-32R6 (Big-endian)", None),
(CS_ARCH_PPC, CS_MODE_BIG_ENDIAN, PPC_CODE, "PPC-64", None),
(CS_ARCH_PPC, CS_MODE_BIG_ENDIAN + CS_MODE_QPX, PPC_CODE2, "PPC-64 + QPX", None),
(CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN, SPARC_CODE, "Sparc", None),
(CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN + CS_MODE_V9, SPARCV9_CODE, "SparcV9", None),
(CS_ARCH_SYSZ, 0, SYSZ_CODE, "SystemZ", None),
(CS_ARCH_XCORE, 0, XCORE_CODE, "XCore", None),
(CS_ARCH_M68K, CS_MODE_BIG_ENDIAN | CS_MODE_M68K_040, M68K_CODE, "M68K", None),
(CS_ARCH_M680X, CS_MODE_M680X_6809, M680X_CODE, "M680X_M6809", None),
(CS_ARCH_MOS65XX, 0, MOS65XX_CODE, "MOS65XX", None),
(CS_ARCH_BPF, CS_MODE_LITTLE_ENDIAN | CS_MODE_BPF_EXTENDED, EBPF_CODE, "eBPF", None),
(CS_ARCH_ALPHA, CS_MODE_LITTLE_ENDIAN, ALPHA_CODE, "Alpha (Little-endian)", None),
(CS_ARCH_ALPHA, CS_MODE_BIG_ENDIAN, ALPHA_CODE_BE, "Alpha (Big-endian)", None),
(CS_ARCH_HPPA, CS_MODE_BIG_ENDIAN | CS_MODE_HPPA_20, HPPA_20_CODE_BE, "HPPA 2.0 (Big-endian)", None),
(CS_ARCH_HPPA, CS_MODE_LITTLE_ENDIAN | CS_MODE_HPPA_20, HPPA_20_CODE, "HPPA 2.0 (Little-endian)", None),
(CS_ARCH_HPPA, CS_MODE_BIG_ENDIAN | CS_MODE_HPPA_11, HPPA_11_CODE_BE, "HPPA 1.1 (Big-endian)", None),
(CS_ARCH_HPPA, CS_MODE_LITTLE_ENDIAN | CS_MODE_HPPA_11, HPPA_11_CODE, "HPPA 1.1 (Little-endian)", None),
)
def print_detail(insn):
print("0x%x:\t%s\t%s // insn-ID: %u, insn-mnem: %s" \
% (insn.address, insn.mnemonic, insn.op_str, insn.id, \
insn.insn_name()))
# "data" instruction generated by SKIPDATA option has no detail
if insn.id == 0:
return
if len(insn.regs_read) > 0:
print("\tImplicit registers read: ", end='')
for m in insn.regs_read:
print("%s " % insn.reg_name(m), end='')
print()
if len(insn.regs_write) > 0:
print("\tImplicit registers modified: ", end='')
for m in insn.regs_write:
print("%s " % insn.reg_name(m), end='')
print()
if len(insn.groups) > 0:
print("\tThis instruction belongs to groups: ", end='')
for m in insn.groups:
print("%s " % insn.group_name(m), end='')
print()
# ## Test class Cs
def test_class():
for (arch, mode, code, comment, syntax) in all_tests:
print('*' * 16)
print("Platform: %s" % comment)
print("Code: %s" % to_hex(code))
print("Disasm:")
try:
md = Cs(arch, mode)
md.detail = True
if syntax is not None:
md.syntax = syntax
for insn in md.disasm(code, 0x1000):
print_detail(insn)
print("0x%x:" % (insn.address + insn.size))
print()
except CsError as e:
print("ERROR: %s" % e)
if __name__ == '__main__':
test_class()

View File

@ -1,48 +0,0 @@
#!/usr/bin/env python3
# Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
from capstone import *
from xprint import to_hex
EVM_CODE = b"\x60\x61\x50"
all_tests = (
(CS_ARCH_EVM, 0, EVM_CODE, "EVM"),
)
def test_class():
address = 0x80001000
for (arch, mode, code, comment) in all_tests:
print("*" * 16)
print("Platform: %s" % comment)
print("Code: %s " % to_hex(code))
print("Disasm:")
try:
md = Cs(arch, mode)
md.detail = True
for i in md.disasm(code, address):
print("0x%x:\t%s\t%s" %(i.address, i.mnemonic, i.op_str))
if i.pop > 0:
print("\tPop: %u" %i.pop)
if i.push > 0:
print("\tPush: %u" %i.push)
if i.fee > 0:
print("\tGas fee: %u" %i.fee)
if len(i.groups) > 0:
print("\tGroups: ", end=''),
for m in i.groups:
print("%s " % i.group_name(m), end=''),
print()
print ("0x%x:\n" % (i.address + i.size))
except CsError as e:
print("ERROR: %s" % e.__str__())
if __name__ == '__main__':
test_class()

View File

@ -1,74 +0,0 @@
#!/usr/bin/env python3
# Capstone Python bindings, by Dmitry Sibirtsev <sibirtsev_dl@gmail.com>
from capstone import *
from capstone.hppa import *
from xprint import to_x, to_hex
HPPA_20_CODE_BE = b'\x00\x20\x50\xa2\x00\x01\x58\x20\x00\x00\x44\xa1\x00\x41\x18\x40\x00\x20\x08\xa2\x01\x60\x48\xa1\x01\x61\x18\xc0\x00\x00\x14\xa1\x00\x0f\x0d\x61\x00\x0f\x0e\x61\x00\x01\x18\x60\x00\x00\x0c\x00\x00\x00\x0c\xa0\x03\xff\xc0\x1f\x00\x00\x04\x00\x00\x10\x04\x00\x04\x22\x51\x83\x04\x22\x51\xc3\x04\x22\x51\x83\x04\x2f\x71\x83\x04\x2f\x71\xc3\x04\x2f\x71\x83\x04\x41\x53\x43\x04\x41\x53\x63\x04\x41\x53\x03\x04\x41\x12\x00\x04\x41\x16\x00\x04\x41\x16\x20\x04\x41\x42\x00\x04\x41\x46\x00\x04\x41\x46\x20\x04\x41\x12\x40\x04\x41\x12\x60\x04\x41\x42\x40\x04\x41\x42\x60\x04\x41\x18\x00\x04\x41\x08\x00\x04\x41\x13\x80\x04\x41\x13\xa0\x04\x41\x52\x80\x04\x41\x52\xa0\x04\x5e\x72\x80\x04\x41\x42\x80\x04\x41\x52\xc0\x04\x41\x52\xe0\x04\x41\x42\xc0\x04\x41\x42\xe0\x14\x00\xde\xad'
HPPA_20_CODE = b'\xa2\x50\x20\x00\x20\x58\x01\x00\xa1\x44\x00\x00\x40\x18\x41\x00\xa2\x08\x20\x00\xa1\x48\x60\x01\xc0\x18\x61\x01\xa1\x14\x00\x00\x61\x0d\x0f\x00\x61\x0e\x0f\x00\x60\x18\x01\x00\x00\x0c\x00\x00\xa0\x0c\x00\x00\x1f\xc0\xff\x03\x00\x04\x00\x00\x00\x04\x10\x00\x83\x51\x22\x04\xc3\x51\x22\x04\x83\x51\x22\x04\x83\x71\x2f\x04\xc3\x71\x2f\x04\x83\x71\x2f\x04\x43\x53\x41\x04\x63\x53\x41\x04\x03\x53\x41\x04\x00\x12\x41\x04\x00\x16\x41\x04\x20\x16\x41\x04\x00\x42\x41\x04\x00\x46\x41\x04\x20\x46\x41\x04\x40\x12\x41\x04\x60\x12\x41\x04\x40\x42\x41\x04\x60\x42\x41\x04\x00\x18\x41\x04\x00\x08\x41\x04\x80\x13\x41\x04\xa0\x13\x41\x04\x80\x52\x41\x04\xa0\x52\x41\x04\x80\x72\x5e\x04\x80\x42\x41\x04\xc0\x52\x41\x04\xe0\x52\x41\x04\xc0\x42\x41\x04\xe0\x42\x41\x04\xad\xde\x00\x14'
HPPA_11_CODE_BE = b'\x24\x41\x40\xc3\x24\x41\x60\xc3\x24\x41\x40\xe3\x24\x41\x60\xe3\x24\x41\x68\xe3\x2c\x41\x40\xc3\x2c\x41\x60\xc3\x2c\x41\x40\xe3\x2c\x41\x60\xe3\x2c\x41\x68\xe3\x24\x62\x42\xc1\x24\x62\x62\xc1\x24\x62\x42\xe1\x24\x62\x46\xe1\x24\x62\x62\xe1\x24\x62\x6a\xe1\x2c\x62\x42\xc1\x2c\x62\x62\xc1\x2c\x62\x42\xe1\x2c\x62\x46\xe1\x2c\x62\x62\xe1\x2c\x62\x6a\xe1\x24\x3e\x50\xc2\x24\x3e\x50\xe2\x24\x3e\x70\xe2\x24\x3e\x78\xe2\x2c\x3e\x50\xc2\x2c\x3e\x50\xe2\x2c\x3e\x70\xe2\x2c\x3e\x78\xe2\x24\x5e\x52\xc1\x24\x5e\x52\xe1\x24\x5e\x56\xe1\x24\x5e\x72\xe1\x24\x5e\x7a\xe1\x2c\x5e\x52\xc1\x2c\x5e\x52\xe1\x2c\x5e\x56\xe1\x2c\x5e\x72\xe1\x2c\x5e\x7a\xe1'
HPPA_11_CODE = b'\xc3\x40\x41\x24\xc3\x60\x41\x24\xe3\x40\x41\x24\xe3\x60\x41\x24\xe3\x68\x41\x24\xc3\x40\x41\x2c\xc3\x60\x41\x2c\xe3\x40\x41\x2c\xe3\x60\x41\x2c\xe3\x68\x41\x2c\xc1\x42\x62\x24\xc1\x62\x62\x24\xe1\x42\x62\x24\xe1\x46\x62\x24\xe1\x62\x62\x24\xe1\x6a\x62\x24\xc1\x42\x62\x2c\xc1\x62\x62\x2c\xe1\x42\x62\x2c\xe1\x46\x62\x2c\xe1\x62\x62\x2c\xe1\x6a\x62\x2c\xc2\x50\x3e\x24\xe2\x50\x3e\x24\xe2\x70\x3e\x24\xe2\x78\x3e\x24\xc2\x50\x3e\x2c\xe2\x50\x3e\x2c\xe2\x70\x3e\x2c\xe2\x78\x3e\x2c\xc1\x52\x5e\x24\xe1\x52\x5e\x24\xe1\x56\x5e\x24\xe1\x72\x5e\x24\xe1\x7a\x5e\x24\xc1\x52\x5e\x2c\xe1\x52\x5e\x2c\xe1\x56\x5e\x2c\xe1\x72\x5e\x2c\xe1\x7a\x5e\x2c'
all_tests = (
(CS_ARCH_HPPA, CS_MODE_BIG_ENDIAN | CS_MODE_HPPA_20, HPPA_20_CODE_BE, "HPPA 2.0 (Big-endian)"),
(CS_ARCH_HPPA, CS_MODE_LITTLE_ENDIAN | CS_MODE_HPPA_20, HPPA_20_CODE, "HPPA 2.0 (Little-endian)"),
(CS_ARCH_HPPA, CS_MODE_BIG_ENDIAN | CS_MODE_HPPA_11, HPPA_11_CODE_BE, "HPPA 1.1 (Big-endian)"),
(CS_ARCH_HPPA, CS_MODE_LITTLE_ENDIAN | CS_MODE_HPPA_11, HPPA_11_CODE, "HPPA 1.1 (Little-endian)"),
)
def print_insn_detail(insn):
# print address, mnemonic and operands
print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
# "data" instruction generated by SKIPDATA option has no detail
if insn.id == 0:
return
if len(insn.operands) > 0:
print("\top_count: %u" % len(insn.operands))
c = 0
for i in insn.operands:
if i.type == HPPA_OP_REG:
print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
if i.type == HPPA_OP_IMM:
print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x(i.imm)))
if i.type == HPPA_OP_IDX_REG:
print("\t\toperands[%u].type: IDX_REG = %s" % (c, insn.reg_name(i.reg)))
if i.type == HPPA_OP_DISP:
print("\t\toperands[%u].type: DISP = 0x%s" % (c, to_x(i.imm)))
if i.type == HPPA_OP_MEM:
print("\t\toperands[%u].type: MEM" % c)
if i.mem.space != HPPA_REG_INVALID:
print("\t\t\toperands[%u].mem.space: REG = %s" % (c, insn.reg_name(i.mem.space)))
print("\t\t\toperands[%u].mem.base: REG = %s" % (c, insn.reg_name(i.mem.base)))
if i.type == HPPA_OP_TARGET:
if i.imm >= 0x8000000000000000:
print("TARGET = -0x%lx" % i.imm)
else:
print("TARGET = 0x%lx" % i.imm)
c += 1
# ## Test class Cs
def test_class():
for (arch, mode, code, comment) in all_tests:
print("*" * 16)
print("Platform: %s" % comment)
print("Code: %s" % to_hex(code))
print("Disasm:")
try:
md = Cs(arch, mode)
md.detail = True
for insn in md.disasm(code, 0x1000):
print_insn_detail(insn)
print()
print("0x%x:\n" % (insn.address + insn.size))
except CsError as e:
print("ERROR: %s" % e)
if __name__ == '__main__':
test_class()

View File

@ -1,153 +0,0 @@
#!/usr/bin/env python3
# Capstone Python bindings, by Wolfgang Schwotzer <wolfgang.schwotzer@gmx.net>
from capstone import *
from capstone.m680x import *
s_access = (
"UNCHANGED", "READ", "WRITE", "READ | WRITE",
)
M6800_CODE = b"\x01\x09\x36\x64\x7f\x74\x10\x00\x90\x10\xA4\x10\xb6\x10\x00\x39"
M6801_CODE = b"\x04\x05\x3c\x3d\x38\x93\x10\xec\x10\xed\x10\x39"
M6805_CODE = b"\x04\x7f\x00\x17\x22\x28\x00\x2e\x00\x40\x42\x5a\x70\x8e\x97\x9c\xa0\x15\xad\x00\xc3\x10\x00\xda\x12\x34\xe5\x7f\xfe"
M6808_CODE = b"\x31\x22\x00\x35\x22\x45\x10\x00\x4b\x00\x51\x10\x52\x5e\x22\x62\x65\x12\x34\x72\x84\x85\x86\x87\x8a\x8b\x8c\x94\x95\xa7\x10\xaf\x10\x9e\x60\x7f\x9e\x6b\x7f\x00\x9e\xd6\x10\x00\x9e\xe6\x7f"
HCS08_CODE = b"\x32\x10\x00\x9e\xae\x9e\xce\x7f\x9e\xbe\x10\x00\x9e\xfe\x7f\x3e\x10\x00\x9e\xf3\x7f\x96\x10\x00\x9e\xff\x7f\x82"
HD6301_CODE = b"\x6b\x10\x00\x71\x10\x00\x72\x10\x10\x39"
M6809_CODE = b"\x06\x10\x19\x1a\x55\x1e\x01\x23\xe9\x31\x06\x34\x55\xa6\x81\xa7\x89\x7f\xff\xa6\x9d\x10\x00\xa7\x91\xa6\x9f\x10\x00\x11\xac\x99\x10\x00\x39\xA6\x07\xA6\x27\xA6\x47\xA6\x67\xA6\x0F\xA6\x10\xA6\x80\xA6\x81\xA6\x82\xA6\x83\xA6\x84\xA6\x85\xA6\x86\xA6\x88\x7F\xA6\x88\x80\xA6\x89\x7F\xFF\xA6\x89\x80\x00\xA6\x8B\xA6\x8C\x10\xA6\x8D\x10\x00\xA6\x91\xA6\x93\xA6\x94\xA6\x95\xA6\x96\xA6\x98\x7F\xA6\x98\x80\xA6\x99\x7F\xFF\xA6\x99\x80\x00\xA6\x9B\xA6\x9C\x10\xA6\x9D\x10\x00\xA6\x9F\x10\x00"
M6811_CODE = b"\x02\x03\x12\x7f\x10\x00\x13\x99\x08\x00\x14\x7f\x02\x15\x7f\x01\x1e\x7f\x20\x00\x8f\xcf\x18\x08\x18\x30\x18\x3c\x18\x67\x18\x8c\x10\x00\x18\x8f\x18\xce\x10\x00\x18\xff\x10\x00\x1a\xa3\x7f\x1a\xac\x1a\xee\x7f\x1a\xef\x7f\xcd\xac\x7f"
CPU12_CODE = b"\x00\x04\x01\x00\x0c\x00\x80\x0e\x00\x80\x00\x11\x1e\x10\x00\x80\x00\x3b\x4a\x10\x00\x04\x4b\x01\x04\x4f\x7f\x80\x00\x8f\x10\x00\xb7\x52\xb7\xb1\xa6\x67\xa6\xfe\xa6\xf7\x18\x02\xe2\x30\x39\xe2\x10\x00\x18\x0c\x30\x39\x10\x00\x18\x11\x18\x12\x10\x00\x18\x19\x00\x18\x1e\x00\x18\x3e\x18\x3f\x00"
HD6309_CODE = b"\x01\x10\x10\x62\x10\x10\x7b\x10\x10\x00\xcd\x49\x96\x02\xd2\x10\x30\x23\x10\x38\x10\x3b\x10\x53\x10\x5d\x11\x30\x43\x10\x11\x37\x25\x10\x11\x38\x12\x11\x39\x23\x11\x3b\x34\x11\x8e\x10\x00\x11\xaf\x10\x11\xab\x10\x11\xf6\x80\x00"
all_tests = (
(CS_ARCH_M680X, CS_MODE_M680X_6301, HD6301_CODE, "M680X_HD6301", None),
(CS_ARCH_M680X, CS_MODE_M680X_6309, HD6309_CODE, "M680X_HD6309", None),
(CS_ARCH_M680X, CS_MODE_M680X_6800, M6800_CODE, "M680X_M6800", None),
(CS_ARCH_M680X, CS_MODE_M680X_6801, M6801_CODE, "M680X_M6801", None),
(CS_ARCH_M680X, CS_MODE_M680X_6805, M6805_CODE, "M680X_M68HC05", None),
(CS_ARCH_M680X, CS_MODE_M680X_6808, M6808_CODE, "M680X_M68HC08", None),
(CS_ARCH_M680X, CS_MODE_M680X_6809, M6809_CODE, "M680X_M6809", None),
(CS_ARCH_M680X, CS_MODE_M680X_6811, M6811_CODE, "M680X_M68HC11", None),
(CS_ARCH_M680X, CS_MODE_M680X_CPU12, CPU12_CODE, "M680X_CPU12", None),
(CS_ARCH_M680X, CS_MODE_M680X_HCS08, HCS08_CODE, "M680X_HCS08", None),
)
# print hex dump from string all upper case
def to_hex_uc(string):
return " ".join("0x%02x" % c for c in string)
# print short hex dump from byte array all upper case
def to_hex_short_uc(byte_array):
return "".join("%02x" % b for b in byte_array)
def print_insn_detail(insn):
# print address, mnemonic and operands
#print("0x%x:\t%s\t%s\t%s" % (insn.address, binascii.hexlify(bytearray(insn.bytes)), \
print("0x%04x: %s\t%s\t%s" % (insn.address, to_hex_short_uc(insn.bytes), \
insn.mnemonic, insn.op_str))
# "data" instruction generated by SKIPDATA option has no detail
if insn.id == 0:
return
if len(insn.operands) > 0:
print("\top_count: %u" % len(insn.operands))
c = 0
for i in insn.operands:
if i.type == M680X_OP_REGISTER:
comment = "";
if (((c == 0) and (insn.flags & M680X_FIRST_OP_IN_MNEM)) or
((c == 1) and (insn.flags & M680X_SECOND_OP_IN_MNEM))):
comment = " (in mnemonic)";
print("\t\toperands[%u].type: REGISTER = %s%s" % (c,
insn.reg_name(i.reg), comment))
if i.type == M680X_OP_CONSTANT:
print("\t\toperands[%u].type: CONSTANT = %u" % (c, i.const_val))
if i.type == M680X_OP_IMMEDIATE:
print("\t\toperands[%u].type: IMMEDIATE = #%d" % (c, i.imm))
if i.type == M680X_OP_DIRECT:
print("\t\toperands[%u].type: DIRECT = 0x%02x" % (c, i.direct_addr))
if i.type == M680X_OP_EXTENDED:
if i.ext.indirect:
indirect = "INDIRECT"
else:
indirect = ""
print("\t\toperands[%u].type: EXTENDED %s = 0x%04x" % (c, indirect, i.ext.address))
if i.type == M680X_OP_RELATIVE:
print("\t\toperands[%u].type: RELATIVE = 0x%04x" % (c, i.rel.address))
if i.type == M680X_OP_INDEXED:
if (i.idx.flags & M680X_IDX_INDIRECT):
indirect = " INDIRECT"
else:
indirect = ""
print("\t\toperands[%u].type: INDEXED%s" % (c, indirect))
if i.idx.base_reg != M680X_REG_INVALID:
print("\t\t\tbase register: %s" % insn.reg_name(i.idx.base_reg))
if i.idx.offset_reg != M680X_REG_INVALID:
print("\t\t\toffset register: %s" % insn.reg_name(i.idx.offset_reg))
if (i.idx.offset_bits != 0) and (i.idx.offset_reg == M680X_REG_INVALID) and (i.idx.inc_dec == 0):
print("\t\t\toffset: %u" % i.idx.offset)
if i.idx.base_reg == M680X_REG_PC:
print("\t\t\toffset address: 0x%04x" % i.idx.offset_addr)
print("\t\t\toffset bits: %u" % i.idx.offset_bits)
if i.idx.inc_dec != 0:
if i.idx.flags & M680X_IDX_POST_INC_DEC:
s_post_pre = "post"
else:
s_post_pre = "pre"
if i.idx.inc_dec > 0:
s_inc_dec = "increment"
else:
s_inc_dec = "decrement"
print("\t\t\t%s %s: %d" %
(s_post_pre, s_inc_dec, abs(i.idx.inc_dec)))
if (i.size != 0):
print("\t\t\tsize: %d" % i.size)
if (i.access != CS_AC_INVALID):
print("\t\t\taccess: %s" % s_access[i.access])
c += 1
(regs_read, regs_write) = insn.regs_access()
if len(regs_read) > 0:
print("\tRegisters read:", end="")
for r in regs_read:
print(" %s" %(insn.reg_name(r)), end="")
print("")
if len(regs_write) > 0:
print("\tRegisters modified:", end="")
for r in regs_write:
print(" %s" %(insn.reg_name(r)), end="")
print("")
if len(insn.groups) > 0:
print("\tgroups_count: %u" % len(insn.groups))
# ## Test class Cs
def test_class():
for (arch, mode, code, comment, syntax) in all_tests:
print("*" * 20)
print("Platform: %s" % comment)
print("Code: %s" % to_hex_uc(code))
print("Disasm:")
try:
md = Cs(arch, mode)
if syntax is not None:
md.syntax = syntax
md.detail = True
for insn in md.disasm(code, 0x1000):
print_insn_detail(insn)
print ()
except CsError as e:
print("ERROR: %s" % e)
if __name__ == '__main__':
test_class()

View File

@ -1,123 +0,0 @@
#!/usr/bin/env python3
# Capstone Python bindings, by Nicolas PLANEL <nplanel@gmail.com>
from capstone import *
from capstone.m68k import *
from xprint import to_hex
M68K_CODE = b"\xf0\x10\xf0\x00\x48\xaf\xff\xff\x7f\xff\x11\xb0\x01\x37\x7f\xff\xff\xff\x12\x34\x56\x78\x01\x33\x10\x10\x10\x10\x32\x32\x32\x32\x4C\x00\x54\x04\x48\xe7\xe0\x30\x4C\xDF\x0C\x07\xd4\x40\x87\x5a\x4e\x71\x02\xb4\xc0\xde\xc0\xde\x5c\x00\x1d\x80\x71\x12\x01\x23\xf2\x3c\x44\x22\x40\x49\x0e\x56\x54\xc5\xf2\x3c\x44\x00\x44\x7a\x00\x00\xf2\x00\x0a\x28\x4E\xB9\x00\x00\x00\x12\x4E\x75"
all_tests = (
(CS_ARCH_M68K, CS_MODE_BIG_ENDIAN | CS_MODE_M68K_040, M68K_CODE, "M68K"),
)
s_addressing_modes = {
0: "<invalid mode>",
1: "Register Direct - Data",
2: "Register Direct - Address",
3: "Register Indirect - Address",
4: "Register Indirect - Address with Postincrement",
5: "Register Indirect - Address with Predecrement",
6: "Register Indirect - Address with Displacement",
7: "Address Register Indirect With Index - 8-bit displacement",
8: "Address Register Indirect With Index - Base displacement",
9: "Memory indirect - Postindex",
10: "Memory indirect - Preindex",
11: "Program Counter Indirect - with Displacement",
12: "Program Counter Indirect with Index - with 8-Bit Displacement",
13: "Program Counter Indirect with Index - with Base Displacement",
14: "Program Counter Memory Indirect - Postindexed",
15: "Program Counter Memory Indirect - Preindexed",
16: "Absolute Data Addressing - Short",
17: "Absolute Data Addressing - Long",
18: "Immediate value",
19: "Branch Displacement",
}
def print_read_write_regs(insn):
for m in insn.regs_read:
print("\treading from reg: %s" % insn.reg_name(m))
for m in insn.regs_write:
print("\twriting to reg: %s" % insn.reg_name(m))
def print_insn_detail(insn):
if len(insn.operands) > 0:
print("\top_count: %u" % (len(insn.operands)))
print_read_write_regs(insn)
print("\tgroups_count: %u" % len(insn.groups))
for i, op in enumerate(insn.operands):
if op.type == M68K_OP_REG:
print("\t\toperands[%u].type: REG = %s" % (i, insn.reg_name(op.reg)))
elif op.type == M68K_OP_IMM:
print("\t\toperands[%u].type: IMM = 0x%x" % (i, op.imm & 0xffffffff))
elif op.type == M68K_OP_MEM:
print("\t\toperands[%u].type: MEM" % (i))
if op.mem.base_reg != M68K_REG_INVALID:
print("\t\t\toperands[%u].mem.base: REG = %s" % (i, insn.reg_name(op.mem.base_reg)))
if op.mem.index_reg != M68K_REG_INVALID:
print("\t\t\toperands[%u].mem.index: REG = %s" % (i, insn.reg_name(op.mem.index_reg)))
mem_index_str = "w"
if op.mem.index_size > 0:
mem_index_str = "l"
print("\t\t\toperands[%u].mem.index: size = %s" % (i, mem_index_str))
if op.mem.disp != 0:
print("\t\t\toperands[%u].mem.disp: 0x%x" % (i, op.mem.disp))
if op.mem.scale != 0:
print("\t\t\toperands[%u].mem.scale: %d" % (i, op.mem.scale))
print("\t\taddress mode: %s" % (s_addressing_modes[op.address_mode]))
elif op.type == M68K_OP_FP_SINGLE:
print("\t\toperands[%u].type: FP_SINGLE" % i)
print("\t\toperands[%u].simm: %f" % (i, op.simm))
elif op.type == M68K_OP_FP_DOUBLE:
print("\t\toperands[%u].type: FP_DOUBLE" % i)
print("\t\toperands[%u].dimm: %lf" % (i, op.dimm))
elif op.type == M68K_OP_REG_BITS:
print("\t\toperands[%u].type: REG_BITS = $%x" % (i, op.register_bits))
elif op.type == M68K_OP_REG_PAIR:
print("\t\toperands[%u].type: REG_PAIR = (%s, %s)" % (i, insn.reg_name(op.reg_pair.reg_0), insn.reg_name(op.reg_pair.reg_1)))
elif op.type == M68K_OP_BR_DISP:
print("\t\toperands[%u].br_disp.disp: 0x%x" % (i, op.br_disp.disp))
print("\t\toperands[%u].br_disp.disp_size: %d" % (i, op.br_disp.disp_size))
print()
# ## Test class Cs
def test_class():
address = 0x01000
for (arch, mode, code, comment) in all_tests:
print("*" * 16)
print("Platform: %s" % comment)
print("Code: %s " % to_hex(code))
print("Disasm:")
try:
md = Cs(arch, mode)
md.detail = True
last_address = 0
for insn in md.disasm(code, address):
last_address = insn.address + insn.size
print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
print_insn_detail(insn)
print("0x%x:\n" % (last_address))
except CsError as e:
print("ERROR: %s" % e.__str__())
if __name__ == '__main__':
test_class()

View File

@ -1,73 +0,0 @@
#!/usr/bin/env python3
# Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
from capstone import *
from capstone.mips import *
from xprint import to_hex, to_x
MIPS_CODE = b"\x0C\x10\x00\x97\x00\x00\x00\x00\x24\x02\x00\x0c\x8f\xa2\x00\x00\x34\x21\x34\x56"
MIPS_CODE2 = b"\x56\x34\x21\x34\xc2\x17\x01\x00"
MIPS_32R6M = b"\x00\x07\x00\x07\x00\x11\x93\x7c\x01\x8c\x8b\x7c\x00\xc7\x48\xd0"
MIPS_32R6 = b"\xec\x80\x00\x19\x7c\x43\x22\xa0"
MIPS_64SD = b"\x70\x00\xb2\xff"
all_tests = (
(CS_ARCH_MIPS, CS_MODE_MIPS32 + CS_MODE_BIG_ENDIAN, MIPS_CODE, "MIPS-32 (Big-endian)"),
(CS_ARCH_MIPS, CS_MODE_MIPS64 + CS_MODE_LITTLE_ENDIAN, MIPS_CODE2, "MIPS-64-EL (Little-endian)"),
(CS_ARCH_MIPS, CS_MODE_MIPS32R6 + CS_MODE_MICRO + CS_MODE_BIG_ENDIAN, MIPS_32R6M, "MIPS-32R6 | Micro (Big-endian)"),
(CS_ARCH_MIPS, CS_MODE_MIPS32R6 + CS_MODE_BIG_ENDIAN, MIPS_32R6, "MIPS-32R6 (Big-endian)"),
(CS_ARCH_MIPS, CS_MODE_MIPS64 | CS_MODE_MIPS2 | CS_MODE_LITTLE_ENDIAN, MIPS_64SD, "MIPS-64-EL + Mips II (Little-endian)"),
(CS_ARCH_MIPS, CS_MODE_MIPS64 | CS_MODE_LITTLE_ENDIAN, MIPS_64SD, "MIPS-64-EL (Little-endian)"),
)
def print_insn_detail(insn):
# print address, mnemonic and operands
print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
# "data" instruction generated by SKIPDATA option has no detail
if insn.id == 0:
return
if len(insn.operands) > 0:
print("\top_count: %u" % len(insn.operands))
c = -1
for i in insn.operands:
c += 1
if i.type == MIPS_OP_REG:
print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
if i.type == MIPS_OP_IMM:
print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x(i.imm)))
if i.type == MIPS_OP_MEM:
print("\t\toperands[%u].type: MEM" % c)
if i.mem.base != 0:
print("\t\t\toperands[%u].mem.base: REG = %s" \
% (c, insn.reg_name(i.mem.base)))
if i.mem.disp != 0:
print("\t\t\toperands[%u].mem.disp: 0x%s" \
% (c, to_x(i.mem.disp)))
# ## Test class Cs
def test_class():
for (arch, mode, code, comment) in all_tests:
print("*" * 16)
print("Platform: %s" % comment)
print("Code: %s" % to_hex(code))
print("Disasm:")
try:
md = Cs(arch, mode)
md.detail = True
for insn in md.disasm(code, 0x1000):
print_insn_detail(insn)
print()
print("0x%x:\n" % (insn.address + insn.size))
except CsError as e:
print("ERROR: %s" % e)
if __name__ == '__main__':
test_class()

View File

@ -1,94 +0,0 @@
#!/usr/bin/env python3
# Capstone Python bindings, by Sebastian Macke <Sebastian Macke>
from capstone import *
from capstone.mos65xx import *
from xprint import to_hex, to_x
M6502_CODE = b"\xa1\x12\xa5\x12\xa9\x12\xad\x34\x12\xb1\x12\xb5\x12\xb9\x34\x12\xbd\x34\x12\x0d\x34\x12\x00\x81\x87\x6c\x01\x00\x85\xFF\x10\x00\x19\x42\x42\x00\x49\x42"
M65C02_CODE = b"\x1a\x3a\x02\x12\x03\x5c\x34\x12"
MW65C02_CODE = b"\x07\x12\x27\x12\x47\x12\x67\x12\x87\x12\xa7\x12\xc7\x12\xe7\x12\x10\xfe\x0f\x12\xfd\x4f\x12\xfd\x8f\x12\xfd\xcf\x12\xfd"
M65816_CODE = b"\xa9\x34\x12\xad\x34\x12\xbd\x34\x12\xb9\x34\x12\xaf\x56\x34\x12\xbf\x56\x34\x12\xa5\x12\xb5\x12\xb2\x12\xa1\x12\xb1\x12\xa7\x12\xb7\x12\xa3\x12\xb3\x12\xc2\x00\xe2\x00\x54\x34\x12\x44\x34\x12\x02\x12"
all_tests = (
(CS_ARCH_MOS65XX, CS_MODE_MOS65XX_6502, M6502_CODE, "MOS65XX_6502"),
(CS_ARCH_MOS65XX, CS_MODE_MOS65XX_65C02, M65C02_CODE, "MOS65XX_65C02"),
(CS_ARCH_MOS65XX, CS_MODE_MOS65XX_W65C02, MW65C02_CODE, "MOS65XX_W65C02"),
(CS_ARCH_MOS65XX, CS_MODE_MOS65XX_65816_LONG_MX, M65816_CODE, "MOS65XX_65816 (long m/x)"),
)
address_modes=[
"No address mode",
"implied",
"accumulator",
"immediate value",
"relative",
"interrupt signature",
"block move",
"zero page",
"zero page indexed with x",
"zero page indexed with y",
"relative bit branch",
"zero page indirect",
"zero page indexed with x indirect",
"zero page indirect indexed with y",
"zero page indirect long",
"zero page indirect long indexed with y",
"absolute",
"absolute indexed with x",
"absolute indexed with y",
"absolute indirect",
"absolute indexed with x indirect",
"absolute indirect long",
"absolute long",
"absolute long indexed with x",
"stack relative",
"stack relative indirect indexed with y",
]
def print_insn_detail(insn):
# print address, mnemonic and operands
print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
# "data" instruction generated by SKIPDATA option has no detail
if insn.id == 0:
return
print("\taddress mode: %s" % (address_modes[insn.am]))
print("\tmodifies flags: %s" % ('true' if insn.modifies_flags != 0 else 'false'))
if len(insn.operands) > 0:
print("\top_count: %u" % len(insn.operands))
c = -1
for i in insn.operands:
c += 1
if i.type == MOS65XX_OP_REG:
print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
if i.type == MOS65XX_OP_IMM:
print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x(i.imm)))
if i.type == MOS65XX_OP_MEM:
print("\t\toperands[%u].type: MEM = 0x%s" % (c, to_x(i.mem)))
# ## Test class Cs
def test_class():
for (arch, mode, code, comment) in all_tests:
print("*" * 16)
print("Platform: %s" % comment)
print("Code: %s" % to_hex(code))
print("Disasm:")
try:
md = Cs(arch, mode)
md.detail = True
md.syntax = CS_OPT_SYNTAX_MOTOROLA
for insn in md.disasm(code, 0x1000):
print_insn_detail(insn)
print()
print("0x%x:\n" % (insn.address + insn.size))
except CsError as e:
print("ERROR: %s" % e)
if __name__ == '__main__':
test_class()

View File

@ -1,93 +0,0 @@
#!/usr/bin/env python3
# Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
from capstone import *
from capstone.ppc import *
from xprint import to_hex, to_x, to_x_32
PPC_CODE = b"\x43\x20\x0c\x07\x41\x56\xff\x17\x80\x20\x00\x00\x80\x3f\x00\x00\x10\x43\x23\x0e\xd0\x44\x00\x80\x4c\x43\x22\x02\x2d\x03\x00\x80\x7c\x43\x20\x14\x7c\x43\x20\x93\x4f\x20\x00\x21\x4c\xc8\x00\x21\x40\x82\x00\x14"
PPC_CODE2 = b"\x10\x60\x2a\x10\x10\x64\x28\x88\x7c\x4a\x5d\x0f"
PPC_CODE3 = b"\x10\x00\x1f\xec\xe0\x6d\x80\x04\xe4\x6d\x80\x04\x10\x60\x1c\x4c\x10\x60\x1c\x0c\xf0\x6d\x80\x04\xf4\x6d\x80\x04\x10\x60\x1c\x4e\x10\x60\x1c\x0e\x10\x60\x1a\x10\x10\x60\x1a\x11\x10\x63\x20\x2a\x10\x63\x20\x2b\x10\x83\x20\x40\x10\x83\x20\xC0\x10\x83\x20\x00\x10\x83\x20\x80\x10\x63\x20\x24\x10\x63\x20\x25\x10\x63\x29\x3a\x10\x63\x29\x3b\x10\x63\x29\x1c\x10\x63\x29\x1d\x10\x63\x29\x1e\x10\x63\x29\x1f\x10\x63\x24\x20\x10\x63\x24\x21\x10\x63\x24\x60\x10\x63\x24\x61\x10\x63\x24\xA0\x10\x63\x24\xA1\x10\x63\x24\xE0\x10\x63\x24\xE1\x10\x60\x20\x90\x10\x60\x20\x91\x10\x63\x29\x38\x10\x63\x29\x39\x10\x63\x01\x32\x10\x63\x01\x33\x10\x63\x01\x18\x10\x63\x01\x19\x10\x63\x01\x1A\x10\x63\x01\x1B\x10\x60\x19\x10\x10\x60\x19\x11\x10\x60\x18\x50\x10\x60\x18\x51\x10\x63\x29\x3e\x10\x63\x29\x3f\x10\x63\x29\x3c\x10\x63\x29\x3d\x10\x60\x18\x30\x10\x60\x18\x31\x10\x60\x18\x34\x10\x60\x18\x35\x10\x63\x29\x2e\x10\x63\x29\x2f\x10\x63\x20\x28\x10\x63\x20\x29\x10\x63\x29\x14\x10\x63\x29\x15\x10\x63\x29\x16\x10\x63\x29\x17"
all_tests = (
(CS_ARCH_PPC, CS_MODE_BIG_ENDIAN, PPC_CODE, "PPC-64"),
(CS_ARCH_PPC, CS_MODE_BIG_ENDIAN + CS_MODE_QPX, PPC_CODE2, "PPC-64 + QPX"),
(CS_ARCH_PPC, CS_MODE_BIG_ENDIAN + CS_MODE_32 + CS_MODE_PS, PPC_CODE3, "PPC + PS"),
)
def print_insn_detail(insn):
# print address, mnemonic and operands
print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
# "data" instruction generated by SKIPDATA option has no detail
if insn.id == 0:
return
if len(insn.operands) > 0:
print("\top_count: %u" % len(insn.operands))
c = 0
for i in insn.operands:
if i.type == PPC_OP_REG:
print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
if i.type == PPC_OP_IMM:
print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x(i.imm)))
if i.type == PPC_OP_MEM:
print("\t\toperands[%u].type: MEM" % c)
if i.mem.base != PPC_REG_INVALID:
print("\t\t\toperands[%u].mem.base: REG = %s" \
% (c, insn.reg_name(i.mem.base)))
if i.mem.offset != 0:
print("\t\t\toperands[%u].mem.offset: REG = %s" \
% (c, insn.reg_name(i.mem.offset)))
if i.mem.disp != 0:
print("\t\t\toperands[%u].mem.disp: 0x%s" \
% (c, to_x_32(i.mem.disp)))
if i.access == CS_AC_READ:
print("\t\toperands[%u].access: READ" % (c))
elif i.access == CS_AC_WRITE:
print("\t\toperands[%u].access: WRITE" % (c))
elif i.access == CS_AC_READ | CS_AC_WRITE:
print("\t\toperands[%u].access: READ | WRITE" % (c))
c += 1
if insn.bc.pred_cr != PPC_PRED_INVALID or \
insn.bc.pred_ctr != PPC_PRED_INVALID:
print("\tBranch:")
print("\t\tbi: %u" % insn.bc.bi)
print("\t\tbo: %u" % insn.bc.bo)
if insn.bc.bh != PPC_BH_INVALID:
print("\t\tbh: %u" %insn.bc.bh)
if insn.bc.pred_cr != PPC_PRED_INVALID:
print("\t\tcrX: %s" % insn.reg_name(insn.bc.crX))
print("\t\tpred CR-bit: %u" % insn.bc.pred_cr)
if insn.bc.pred_ctr != PPC_PRED_INVALID:
print("\t\tpred CTR: %u" % insn.bc.pred_ctr)
if insn.bc.hint != PPC_BR_NOT_GIVEN:
print("\t\thint: %u" % insn.bc.hint)
if insn.update_cr0:
print("\tUpdate-CR0: True")
# ## Test class Cs
def test_class():
for (arch, mode, code, comment) in all_tests:
print("*" * 16)
print("Platform: %s" % comment)
print("Code: %s" % to_hex(code))
print("Disasm:")
try:
md = Cs(arch, mode)
md.detail = True
for insn in md.disasm(code, 0x1000):
print_insn_detail(insn)
print ()
print("0x%x:\n" % (insn.address + insn.size))
except CsError as e:
print("ERROR: %s" % e)
if __name__ == '__main__':
test_class()

View File

@ -1,79 +0,0 @@
#!/usr/bin/env python3
# Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
from capstone import *
from capstone.riscv import *
from xprint import to_x, to_hex
RISCV_CODE32 = b"\x37\x34\x00\x00\x97\x82\x00\x00\xef\x00\x80\x00\xef\xf0\x1f\xff\xe7\x00\x45\x00\xe7\x00\xc0\xff\x63\x05\x41\x00\xe3\x9d\x61\xfe\x63\xca\x93\x00\x63\x53\xb5\x00\x63\x65\xd6\x00\x63\x76\xf7\x00\x03\x88\x18\x00\x03\x99\x49\x00\x03\xaa\x6a\x00\x03\xcb\x2b\x01\x03\xdc\x8c\x01\x23\x86\xad\x03\x23\x9a\xce\x03\x23\x8f\xef\x01\x93\x00\xe0\x00\x13\xa1\x01\x01\x13\xb2\x02\x7d\x13\xc3\x03\xdd\x13\xe4\xc4\x12\x13\xf5\x85\x0c\x13\x96\xe6\x01\x13\xd7\x97\x01\x13\xd8\xf8\x40\x33\x89\x49\x01\xb3\x0a\x7b\x41\x33\xac\xac\x01\xb3\x3d\xde\x01\x33\xd2\x62\x40\xb3\x43\x94\x00\x33\xe5\xc5\x00\xb3\x76\xf7\x00\xb3\x54\x39\x01\xb3\x50\x31\x00\x33\x9f\x0f\x00\x73\x15\x04\xb0\xf3\x56\x00\x10\x33\x05\x7b\x03\xb3\x45\x9c\x03\x33\x66\xbd\x03\x2f\xa4\x02\x10\xaf\x23\x65\x18\x2f\x27\x2f\x01\x43\xf0\x20\x18\xd3\x72\x73\x00\x53\xf4\x04\x58\x53\x85\xc5\x28\x53\x2e\xde\xa1\xd3\x84\x05\xf0\x53\x06\x05\xe0\x53\x75\x00\xc0\xd3\xf0\x05\xd0\xd3\x15\x08\xe0\x87\xaa\x75\x00\x27\x27\x66\x01\x43\xf0\x20\x1a\xd3\x72\x73\x02\x53\xf4\x04\x5a\x53\x85\xc5\x2a\x53\x2e\xde\xa3"
RISCV_CODE64 = b"\x13\x04\xa8\x7a\xbb\x07\x9c\x02\xbb\x40\x5d\x02\x3b\x63\xb7\x03\x2f\xb4\x02\x10\xaf\x33\x65\x18\x2f\x37\x2f\x01\x53\x75\x20\xc0\xd3\xf0\x25\xd0\xd3\x84\x05\xf2\x53\x06\x05\xe2\x53\x75\x00\xc2\xd3\x80\x05\xd2\xd3\x15\x08\xe2\x87\xba\x75\x00\x27\x37\x66\x01"
RISCV_CODEC = b"\xe8\x1f\x7d\x61\x80\x25\x00\x46\x88\xa2\x04\xcb\x55\x13\xf2\x93\x5d\x45\x19\x80\x15\x68\x2a\xa4\x62\x24\xa6\xff\x2a\x65\x76\x86\x65\xdd\x01\x00\xfd\xaf\x82\x82\x11\x20\x82\x94"
all_tests = (
(CS_ARCH_RISCV, CS_MODE_RISCV32, RISCV_CODE32, "riscv32"),
(CS_ARCH_RISCV, CS_MODE_RISCV64, RISCV_CODE64, "riscv64"),
(CS_ARCH_RISCV, CS_MODE_RISCVC, RISCV_CODEC, "riscvc"),
)
def print_insn_detail(insn):
# print address, mnemonic and operands
print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
# "data" instruction generated by SKIPDATA option has no detail
if insn.id == 0:
return
if len(insn.operands) > 0:
print("\top_count: %u" % len(insn.operands))
c = 0
for i in insn.operands:
if i.type == RISCV_OP_REG:
print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
if i.type == RISCV_OP_IMM:
print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x(i.imm)))
if i.type == RISCV_OP_MEM:
print("\t\toperands[%u].type: MEM" % c)
if i.mem.base != 0:
print("\t\t\toperands[%u].mem.base: REG = %s" \
% (c, insn.reg_name(i.mem.base)))
if i.mem.disp != 0:
print("\t\t\toperands[%u].mem.disp: 0x%s" \
% (c, to_x(i.mem.disp)))
if i.access == CS_AC_READ:
print("\t\toperands[%u].access: READ" % (c))
elif i.access == CS_AC_WRITE:
print("\t\toperands[%u].access: WRITE" % (c))
elif i.access == CS_AC_READ | CS_AC_WRITE:
print("\t\toperands[%u].access: READ | WRITE" % (c))
c += 1
if len(insn.groups) > 0:
print('\tgroups: ' + ' '.join(map(lambda g: insn.group_name(g), insn.groups)))
# ## Test class Cs
def test_class():
for (arch, mode, code, comment) in all_tests:
print("*" * 16)
print("Platform: %s" %comment)
print("Code: %s" % to_hex(code))
print("Disasm:")
try:
md = Cs(arch, mode)
md.detail = True
for insn in md.disasm(code, 0x1000):
print_insn_detail(insn)
print ()
print("0x%x:\n" % (insn.address + insn.size))
except CsError as e:
print("ERROR: %s" %e)
if __name__ == '__main__':
test_class()

View File

@ -1,96 +0,0 @@
#!/usr/bin/env python3
# Capstone Python bindings, by Peace-Maker <peacemakerctf@gmail.com>
from capstone import *
from capstone.sh import *
from xprint import to_x, to_hex
SH4A_CODE = b"\x0c\x31\x10\x20\x22\x21\x36\x64\x46\x25\x12\x12\x1c\x02\x08\xc1\x05\xc7\x0c\x71\x1f\x02\x22\xcf\x06\x89\x23\x00\x2b\x41\x0b\x00\x0e\x40\x32\x00\x0a\xf1\x09\x00"
SH2A_CODE = b"\x32\x11\x92\x00\x32\x49\x31\x00"
all_tests = (
(CS_ARCH_SH, CS_MODE_SH4A | CS_MODE_SHFPU, SH4A_CODE, "SH_SH4A"),
(CS_ARCH_SH, CS_MODE_SH2A | CS_MODE_SHFPU | CS_MODE_BIG_ENDIAN, SH2A_CODE, "SH_SH2A"),
)
reg_address_msg = [
"Register indirect",
"Register indirect with predecrement",
"Register indirect with postincrement",
]
def print_read_write_regs(insn):
if len(insn.regs_read) > 0:
print("\tRegisters read: %s" % " ".join(insn.reg_name(m) for m in insn.regs_read))
if len(insn.regs_write) > 0:
print("\tRegisters modified: %s" % " ".join(insn.reg_name(m) for m in insn.regs_write))
def print_insn_detail(insn):
# print address, mnemonic and operands
print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
# "data" instruction generated by SKIPDATA option has no detail
if insn.id == 0:
return
if len(insn.operands) > 0:
print("\top_count: %u" % len(insn.operands))
c = 0
for i in insn.operands:
if i.type == SH_OP_REG:
print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
elif i.type == SH_OP_IMM:
print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x(i.imm)))
elif i.type == SH_OP_MEM:
print("\t\toperands[%u].type: MEM " % c)
if i.mem.address in [SH_OP_MEM_REG_IND, SH_OP_MEM_REG_POST, SH_OP_MEM_REG_PRE]:
print("%s REG %s" % (reg_address_msg[i.mem.address - SH_OP_MEM_REG_IND], insn.reg_name(i.mem.reg)))
elif i.mem.address == SH_OP_MEM_REG_DISP:
print("Register indirect with displacement REG %s, DISP %d" % (insn.reg_name(i.mem.reg), i.mem.disp))
elif i.mem.address == SH_OP_MEM_REG_R0:
print("R0 indexed")
elif i.mem.address == SH_OP_MEM_GBR_DISP:
print("GBR base with displacement DISP %d" % i.mem.disp)
elif i.mem.address == SH_OP_MEM_GBR_R0:
print("GBR base with R0 indexed")
elif i.mem.address == SH_OP_MEM_PCR:
print("PC relative Address=0x%08x" % i.mem.disp)
elif i.mem.address == SH_OP_MEM_TBR_DISP:
print("TBR base with displacement DISP %d", i.mem.disp)
else:
print("Unknown addressing mode %x" % i.mem.address)
if i.sh_size != 0:
print("\t\t\tsh_size: %u" % i.sh_size)
c += 1
print_read_write_regs(insn)
if len(insn.groups) > 0:
print('\tgroups: ' + ' '.join(map(lambda g: insn.group_name(g), insn.groups)))
# ## Test class Cs
def test_class():
for (arch, mode, code, comment) in all_tests:
print("*" * 16)
print("Platform: %s" %comment)
print("Code: %s" % to_hex(code))
print("Disasm:")
try:
md = Cs(arch, mode)
md.detail = True
for insn in md.disasm(code, 0x80000000):
print_insn_detail(insn)
print()
print("0x%x:" % (insn.address + insn.size))
except CsError as e:
print("ERROR: %s" %e)
if __name__ == '__main__':
test_class()

View File

@ -1,74 +0,0 @@
#!/usr/bin/env python3
# Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
from capstone import *
from capstone.sparc import *
from xprint import to_hex, to_x_32
SPARC_CODE = b"\x80\xa0\x40\x02\x85\xc2\x60\x08\x85\xe8\x20\x01\x81\xe8\x00\x00\x90\x10\x20\x01\xd5\xf6\x10\x16\x21\x00\x00\x0a\x86\x00\x40\x02\x01\x00\x00\x00\x12\xbf\xff\xff\x10\xbf\xff\xff\xa0\x02\x00\x09\x0d\xbf\xff\xff\xd4\x20\x60\x00\xd4\x4e\x00\x16\x2a\xc2\x80\x03"
SPARCV9_CODE = b"\x81\xa8\x0a\x24\x89\xa0\x10\x20\x89\xa0\x1a\x60\x89\xa0\x00\xe0"
all_tests = (
(CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN, SPARC_CODE, "Sparc"),
(CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN+CS_MODE_V9, SPARCV9_CODE, "SparcV9"),
)
def print_insn_detail(insn):
# print address, mnemonic and operands
print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
# "data" instruction generated by SKIPDATA option has no detail
if insn.id == 0:
return
if len(insn.operands) > 0:
print("\top_count: %u" % len(insn.operands))
c = 0
for i in insn.operands:
if i.type == SPARC_OP_REG:
print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
if i.type == SPARC_OP_IMM:
print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x_32(i.imm)))
if i.type == SPARC_OP_MEM:
print("\t\toperands[%u].type: MEM" % c)
if i.mem.base != 0:
print("\t\t\toperands[%u].mem.base: REG = %s" \
% (c, insn.reg_name(i.mem.base)))
if i.mem.index != 0:
print("\t\t\toperands[%u].mem.index: REG = %s" \
% (c, insn.reg_name(i.mem.index)))
if i.mem.disp != 0:
print("\t\t\toperands[%u].mem.disp: 0x%s" \
% (c, to_x_32(i.mem.disp)))
c += 1
if insn.cc:
print("\tCode condition: %u" % insn.cc)
if insn.hint:
print("\tHint code: %u" % insn.hint)
# ## Test class Cs
def test_class():
for (arch, mode, code, comment) in all_tests:
print("*" * 16)
print("Platform: %s" % comment)
print("Code: %s" % to_hex(code))
print("Disasm:")
try:
md = Cs(arch, mode)
md.detail = True
for insn in md.disasm(code, 0x1000):
print_insn_detail(insn)
print ()
print("0x%x:\n" % (insn.address + insn.size))
except CsError as e:
print("ERROR: %s" %e)
if __name__ == '__main__':
test_class()

View File

@ -1,76 +0,0 @@
#!/usr/bin/env python3
# Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
from capstone import *
from capstone.systemz import *
from xprint import to_x, to_hex
SYSZ_CODE = b"\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78\xec\x18\x00\x00\xc1\x7f"
all_tests = (
(CS_ARCH_SYSZ, 0, SYSZ_CODE, "SystemZ"),
)
def print_insn_detail(insn):
# print address, mnemonic and operands
print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
# "data" instruction generated by SKIPDATA option has no detail
if insn.id == 0:
return
if len(insn.operands) > 0:
print("\top_count: %u" % len(insn.operands))
c = 0
for i in insn.operands:
if i.type == SYSZ_OP_REG:
print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
if i.type == SYSZ_OP_ACREG:
print("\t\toperands[%u].type: ACREG = %u" % (c, i.reg))
if i.type == SYSZ_OP_IMM:
print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x(i.imm)))
if i.type == SYSZ_OP_MEM:
print("\t\toperands[%u].type: MEM" % c)
if i.mem.base != 0:
print("\t\t\toperands[%u].mem.base: REG = %s" \
% (c, insn.reg_name(i.mem.base)))
if i.mem.index != 0:
print("\t\t\toperands[%u].mem.index: REG = %s" \
% (c, insn.reg_name(i.mem.index)))
if i.mem.length != 0:
print("\t\t\toperands[%u].mem.length: 0x%s" \
% (c, to_x(i.mem.length)))
if i.mem.disp != 0:
print("\t\t\toperands[%u].mem.disp: 0x%s" \
% (c, to_x(i.mem.disp)))
c += 1
if insn.cc:
print("\tConditional code: %u" % insn.cc)
# ## Test class Cs
def test_class():
for (arch, mode, code, comment) in all_tests:
print("*" * 16)
print("Platform: %s" %comment)
print("Code: %s" % to_hex(code))
print("Disasm:")
try:
md = Cs(arch, mode)
md.detail = True
for insn in md.disasm(code, 0x1000):
print_insn_detail(insn)
print ()
print("0x%x:\n" % (insn.address + insn.size))
except CsError as e:
print("ERROR: %s" %e)
if __name__ == '__main__':
test_class()

View File

@ -1,113 +0,0 @@
#!/usr/bin/env python3
# Capstone Python bindings, by Fotis Loukos <me@fotisl.com>
from capstone import *
from capstone.tms320c64x import *
from xprint import to_x, to_hex, to_x_32
TMS320C64X_CODE = b"\x01\xac\x88\x40\x81\xac\x88\x43\x00\x00\x00\x00\x02\x90\x32\x96\x02\x80\x46\x9e\x05\x3c\x83\xe6\x0b\x0c\x8b\x24"
all_tests = (
(CS_ARCH_TMS320C64X, 0, TMS320C64X_CODE, "TMS320C64x"),
)
def print_insn_detail(insn):
# print address, mnemonic and operands
print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
# "data" instruction generated by SKIPDATA option has no detail
if insn.id == 0:
return
if len(insn.operands) > 0:
print("\top_count: %u" % len(insn.operands))
c = 0
for i in insn.operands:
if i.type == TMS320C64X_OP_REG:
print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
if i.type == TMS320C64X_OP_IMM:
print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x(i.imm)))
if i.type == TMS320C64X_OP_MEM:
print("\t\toperands[%u].type: MEM" % c)
if i.mem.base != 0:
print("\t\t\toperands[%u].mem.base: REG = %s" \
% (c, insn.reg_name(i.mem.base)))
if i.mem.disptype == TMS320C64X_MEM_DISP_INVALID:
print("\t\t\toperands[%u].mem.disptype: Invalid" % (c))
print("\t\t\toperands[%u].mem.disp: 0x%s" \
% (c, to_x(i.mem.disp)))
if i.mem.disptype == TMS320C64X_MEM_DISP_CONSTANT:
print("\t\t\toperands[%u].mem.disptype: Constant" % (c))
print("\t\t\toperands[%u].mem.disp: 0x%s" \
% (c, to_x(i.mem.disp)))
if i.mem.disptype == TMS320C64X_MEM_DISP_REGISTER:
print("\t\t\toperands[%u].mem.disptype: Register" % (c))
print("\t\t\toperands[%u].mem.disp: %s" \
% (c, insn.reg_name(i.mem.disp)))
print("\t\t\toperands[%u].mem.unit: %u" % (c, i.mem.unit))
if i.mem.direction == TMS320C64X_MEM_DIR_INVALID:
print("\t\t\toperands[%u].mem.direction: Invalid" % (c))
if i.mem.direction == TMS320C64X_MEM_DIR_FW:
print("\t\t\toperands[%u].mem.direction: Forward" % (c))
if i.mem.direction == TMS320C64X_MEM_DIR_BW:
print("\t\t\toperands[%u].mem.direction: Backward" % (c))
if i.mem.modify == TMS320C64X_MEM_MOD_INVALID:
print("\t\t\toperands[%u].mem.modify: Invalid" % (c))
if i.mem.modify == TMS320C64X_MEM_MOD_NO:
print("\t\t\toperands[%u].mem.modify: No" % (c))
if i.mem.modify == TMS320C64X_MEM_MOD_PRE:
print("\t\t\toperands[%u].mem.modify: Pre" % (c))
if i.mem.modify == TMS320C64X_MEM_MOD_POST:
print("\t\t\toperands[%u].mem.modify: Post" % (c))
print("\t\t\toperands[%u].mem.scaled: %u" % (c, i.mem.scaled))
if i.type == TMS320C64X_OP_REGPAIR:
print("\t\toperands[%u].type: REGPAIR = %s:%s" % (c, insn.reg_name(i.reg + 1), insn.reg_name(i.reg)))
c += 1
print("\tFunctional unit: ", end="")
if insn.funit.unit == TMS320C64X_FUNIT_D:
print("D%u" % insn.funit.side)
elif insn.funit.unit == TMS320C64X_FUNIT_L:
print("L%u" % insn.funit.side)
elif insn.funit.unit == TMS320C64X_FUNIT_M:
print("M%u" % insn.funit.side)
elif insn.funit.unit == TMS320C64X_FUNIT_S:
print("S%u" % insn.funit.side)
elif insn.funit.unit == TMS320C64X_FUNIT_NO:
print("No Functional Unit")
else:
print("Unknown (Unit %u, Side %u)" % (insn.funit.unit, insn.funit.side))
if insn.funit.crosspath == 1:
print("\tCrosspath: 1")
if insn.condition.reg != TMS320C64X_REG_INVALID:
print("\tCondition: [%c%s]" % ("!" if insn.condition.zero == 1 else " ", insn.reg_name(insn.condition.reg)))
print("\tParallel: %s" % ("true" if insn.parallel == 1 else "false"))
print()
# ## Test class Cs
def test_class():
for (arch, mode, code, comment) in all_tests:
print("*" * 16)
print("Platform: %s" %comment)
print("Code: %s" % to_hex(code))
print("Disasm:")
try:
md = Cs(arch, mode)
md.detail = True
for insn in md.disasm(code, 0x1000):
print_insn_detail(insn)
print("0x%x:\n" % (insn.address + insn.size))
except CsError as e:
print("ERROR: %s" %e)
if __name__ == '__main__':
test_class()

View File

@ -1,63 +0,0 @@
#!/usr/bin/env python3
# Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
from capstone import *
from capstone.tricore import *
from xprint import to_hex, to_x
TRICORE_CODE = b"\x09\xcf\xbc\xf5\x09\xf4\x01\x00\x89\xfb\x8f\x74\x89\xfe\x48\x01\x29\x00\x19\x25\x29\x03\x09\xf4\x85\xf9\x68\x0f\x16\x01"
all_tests = (
(CS_ARCH_TRICORE, CS_MODE_TRICORE_162, TRICORE_CODE, "TriCore"),
)
def print_insn_detail(insn):
# print address, mnemonic and operands
print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
# "data" instruction generated by SKIPDATA option has no detail
if insn.id == 0:
return
if len(insn.operands) > 0:
print("\top_count: %u" % len(insn.operands))
c = 0
for i in insn.operands:
if i.type == TRICORE_OP_REG:
print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
if i.type == TRICORE_OP_IMM:
print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x(i.imm)))
if i.type == TRICORE_OP_MEM:
print("\t\toperands[%u].type: MEM" % c)
if i.mem.base != 0:
print("\t\t\toperands[%u].mem.base: REG = %s" \
% (c, insn.reg_name(i.mem.base)))
if i.mem.disp != 0:
print("\t\t\toperands[%u].mem.disp: 0x%s" \
% (c, to_x(i.mem.disp)))
c += 1
print()
# ## Test class Cs
def test_class():
for (arch, mode, code, comment) in all_tests:
print("*" * 16)
print("Platform: %s" % comment)
print("Code: %s" % to_hex(code))
print("Disasm:")
try:
md = Cs(arch, mode)
md.detail = True
for insn in md.disasm(code, 0x1000):
print_insn_detail(insn)
print("0x%x:" % (insn.address + insn.size))
except CsError as e:
print("ERROR: %s" % e)
if __name__ == '__main__':
test_class()

View File

@ -1,80 +0,0 @@
#!/usr/bin/env python3
# Capstone Python bindings, by Peace-Maker <peacemakerctf@gmail.com>
from capstone import *
from capstone.wasm import *
from xprint import to_hex
WASM_CODE = b"\x20\x00\x20\x01\x41\x20\x10\xc9\x01\x45\x0b"
all_tests = (
(CS_ARCH_WASM, 0, WASM_CODE, "WASM"),
)
def print_insn_detail(insn):
# print address, mnemonic and operands
print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
# "data" instruction generated by SKIPDATA option has no detail
if insn.id == 0:
return
if len(insn.groups) > 0:
print("\tGroups: ", end="")
for group in insn.groups:
print("%s " % insn.group_name(group), end="")
print()
if len(insn.operands) > 0:
print("\tOperand count: %u" % len(insn.operands))
c = 0
for i in insn.operands:
if i.type == WASM_OP_INT7:
print("\t\tOperand[%u] type: int7" % c)
print("\t\tOperand[%u] value: %d" % (c, i.int7))
elif i.type == WASM_OP_VARUINT32:
print("\t\tOperand[%u] type: varuint32" % c)
print("\t\tOperand[%u] value: %#x" % (c, i.varuint32))
elif i.type == WASM_OP_VARUINT64:
print("\t\tOperand[%u] type: varuint64" % c)
print("\t\tOperand[%u] value: %#x" % (c, i.varuint64))
elif i.type == WASM_OP_UINT32:
print("\t\tOperand[%u] type: uint32" % c)
print("\t\tOperand[%u] value: %#x" % (c, i.uint32))
elif i.type == WASM_OP_UINT64:
print("\t\tOperand[%u] type: uint64" % c)
print("\t\tOperand[%u] value: %#x" % (c, i.uint64))
elif i.type == WASM_OP_IMM:
print("\t\tOperand[%u] type: imm" % c)
print("\t\tOperand[%u] value: %#x %#x" % (c, i.immediate[0], i.immediate[1]))
elif i.type == WASM_OP_BRTABLE:
print("\t\tOperand[%u] type: brtable" % c)
print("\t\tOperand[%u] value: length=%#x, address=%#x, default_target=%#x" % (c, i.brtable.length, i.brtable.address, i.brtable.default_target))
print("\t\tOperand[%u] size: %u" % (c, i.size))
c += 1
# ## Test class Cs
def test_class():
for (arch, mode, code, comment) in all_tests:
print("*" * 16)
print("Platform: %s" % comment)
print("Code: %s" % to_hex(code))
print("Disasm:")
try:
md = Cs(arch, mode)
md.detail = True
for insn in md.disasm(code, 0xffff):
print_insn_detail(insn)
print()
print("0x%x:\n" % (insn.address + insn.size))
except CsError as e:
print("ERROR: %s" % e)
if __name__ == '__main__':
test_class()

View File

@ -1,344 +0,0 @@
#!/usr/bin/env python3
# Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
from capstone import *
from capstone.x86 import *
from xprint import to_hex, to_x
X86_CODE64 = b"\x55\x48\x8b\x05\xb8\x13\x00\x00\xe9\xea\xbe\xad\xde\xff\x25\x23\x01\x00\x00\xe8\xdf\xbe\xad\xde\x74\xff"
X86_CODE16 = b"\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00\x05\x23\x01\x00\x00\x36\x8b\x84\x91\x23\x01\x00\x00\x41\x8d\x84\x39\x89\x67\x00\x00\x8d\x87\x89\x67\x00\x00\xb4\xc6\x66\xe9\xb8\x00\x00\x00\x67\xff\xa0\x23\x01\x00\x00\x66\xe8\xcb\x00\x00\x00\x74\xfc"
X86_CODE32 = b"\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00\x05\x23\x01\x00\x00\x36\x8b\x84\x91\x23\x01\x00\x00\x41\x8d\x84\x39\x89\x67\x00\x00\x8d\x87\x89\x67\x00\x00\xb4\xc6\xe9\xea\xbe\xad\xde\xff\xa0\x23\x01\x00\x00\xe8\xdf\xbe\xad\xde\x74\xff"
all_tests = (
(CS_ARCH_X86, CS_MODE_16, X86_CODE16, "X86 16bit (Intel syntax)", None),
(CS_ARCH_X86, CS_MODE_32, X86_CODE32, "X86 32 (AT&T syntax)", CS_OPT_SYNTAX_ATT),
(CS_ARCH_X86, CS_MODE_32, X86_CODE32, "X86 32 (Intel syntax)", None),
(CS_ARCH_X86, CS_MODE_64, X86_CODE64, "X86 64 (Intel syntax)", None),
)
def get_eflag_name(eflag):
if eflag == X86_EFLAGS_UNDEFINED_OF:
return "UNDEF_OF"
elif eflag == X86_EFLAGS_UNDEFINED_SF:
return "UNDEF_SF"
elif eflag == X86_EFLAGS_UNDEFINED_ZF:
return "UNDEF_ZF"
elif eflag == X86_EFLAGS_MODIFY_AF:
return "MOD_AF"
elif eflag == X86_EFLAGS_UNDEFINED_PF:
return "UNDEF_PF"
elif eflag == X86_EFLAGS_MODIFY_CF:
return "MOD_CF"
elif eflag == X86_EFLAGS_MODIFY_SF:
return "MOD_SF"
elif eflag == X86_EFLAGS_MODIFY_ZF:
return "MOD_ZF"
elif eflag == X86_EFLAGS_UNDEFINED_AF:
return "UNDEF_AF"
elif eflag == X86_EFLAGS_MODIFY_PF:
return "MOD_PF"
elif eflag == X86_EFLAGS_UNDEFINED_CF:
return "UNDEF_CF"
elif eflag == X86_EFLAGS_MODIFY_OF:
return "MOD_OF"
elif eflag == X86_EFLAGS_RESET_OF:
return "RESET_OF"
elif eflag == X86_EFLAGS_RESET_CF:
return "RESET_CF"
elif eflag == X86_EFLAGS_RESET_DF:
return "RESET_DF"
elif eflag == X86_EFLAGS_RESET_IF:
return "RESET_IF"
elif eflag == X86_EFLAGS_TEST_OF:
return "TEST_OF"
elif eflag == X86_EFLAGS_TEST_SF:
return "TEST_SF"
elif eflag == X86_EFLAGS_TEST_ZF:
return "TEST_ZF"
elif eflag == X86_EFLAGS_TEST_PF:
return "TEST_PF"
elif eflag == X86_EFLAGS_TEST_CF:
return "TEST_CF"
elif eflag == X86_EFLAGS_RESET_SF:
return "RESET_SF"
elif eflag == X86_EFLAGS_RESET_AF:
return "RESET_AF"
elif eflag == X86_EFLAGS_RESET_TF:
return "RESET_TF"
elif eflag == X86_EFLAGS_RESET_NT:
return "RESET_NT"
elif eflag == X86_EFLAGS_PRIOR_OF:
return "PRIOR_OF"
elif eflag == X86_EFLAGS_PRIOR_SF:
return "PRIOR_SF"
elif eflag == X86_EFLAGS_PRIOR_ZF:
return "PRIOR_ZF"
elif eflag == X86_EFLAGS_PRIOR_AF:
return "PRIOR_AF"
elif eflag == X86_EFLAGS_PRIOR_PF:
return "PRIOR_PF"
elif eflag == X86_EFLAGS_PRIOR_CF:
return "PRIOR_CF"
elif eflag == X86_EFLAGS_PRIOR_TF:
return "PRIOR_TF"
elif eflag == X86_EFLAGS_PRIOR_IF:
return "PRIOR_IF"
elif eflag == X86_EFLAGS_PRIOR_DF:
return "PRIOR_DF"
elif eflag == X86_EFLAGS_TEST_NT:
return "TEST_NT"
elif eflag == X86_EFLAGS_TEST_DF:
return "TEST_DF"
elif eflag == X86_EFLAGS_RESET_PF:
return "RESET_PF"
elif eflag == X86_EFLAGS_PRIOR_NT:
return "PRIOR_NT"
elif eflag == X86_EFLAGS_MODIFY_TF:
return "MOD_TF"
elif eflag == X86_EFLAGS_MODIFY_IF:
return "MOD_IF"
elif eflag == X86_EFLAGS_MODIFY_DF:
return "MOD_DF"
elif eflag == X86_EFLAGS_MODIFY_NT:
return "MOD_NT"
elif eflag == X86_EFLAGS_MODIFY_RF:
return "MOD_RF"
elif eflag == X86_EFLAGS_SET_CF:
return "SET_CF"
elif eflag == X86_EFLAGS_SET_DF:
return "SET_DF"
elif eflag == X86_EFLAGS_SET_IF:
return "SET_IF"
else:
return None
def get_fpu_flag_name(flag):
if flag == X86_FPU_FLAGS_MODIFY_C0:
return "MOD_C0"
elif flag == X86_FPU_FLAGS_MODIFY_C1:
return "MOD_C1"
elif flag == X86_FPU_FLAGS_MODIFY_C2:
return "MOD_C2"
elif flag == X86_FPU_FLAGS_MODIFY_C3:
return "MOD_C3"
elif flag == X86_FPU_FLAGS_RESET_C0:
return "RESET_C0"
elif flag == X86_FPU_FLAGS_RESET_C1:
return "RESET_C1"
elif flag == X86_FPU_FLAGS_RESET_C2:
return "RESET_C2"
elif flag == X86_FPU_FLAGS_RESET_C3:
return "RESET_C3"
elif flag == X86_FPU_FLAGS_SET_C0:
return "SET_C0"
elif flag == X86_FPU_FLAGS_SET_C1:
return "SET_C1"
elif flag == X86_FPU_FLAGS_SET_C2:
return "SET_C2"
elif flag == X86_FPU_FLAGS_SET_C3:
return "SET_C3"
elif flag == X86_FPU_FLAGS_UNDEFINED_C0:
return "UNDEF_C0"
elif flag == X86_FPU_FLAGS_UNDEFINED_C1:
return "UNDEF_C1"
elif flag == X86_FPU_FLAGS_UNDEFINED_C2:
return "UNDEF_C2"
elif flag == X86_FPU_FLAGS_UNDEFINED_C3:
return "UNDEF_C3"
elif flag == X86_FPU_FLAGS_TEST_C0:
return "TEST_C0"
elif flag == X86_FPU_FLAGS_TEST_C1:
return "TEST_C1"
elif flag == X86_FPU_FLAGS_TEST_C2:
return "TEST_C2"
elif flag == X86_FPU_FLAGS_TEST_C3:
return "TEST_C3"
else:
return None
def print_insn_detail(mode, insn):
def print_string_hex(comment, str):
print(comment, end=' '),
for c in str:
print("0x%02x " % c, end=''),
print()
# print address, mnemonic and operands
print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
# "data" instruction generated by SKIPDATA option has no detail
if insn.id == 0:
return
# print instruction prefix
print_string_hex("\tPrefix:", insn.prefix)
# print instruction's opcode
print_string_hex("\tOpcode:", insn.opcode)
# print operand's REX prefix (non-zero value is relevant for x86_64 instructions)
print("\trex: 0x%x" % (insn.rex))
# print operand's address size
print("\taddr_size: %u" % (insn.addr_size))
# print modRM byte
print("\tmodrm: 0x%x" % (insn.modrm))
# print modRM offset
if insn.encoding.modrm_offset != 0:
print("\tmodrm_offset: 0x%x" % (insn.encoding.modrm_offset))
# print displacement value
print("\tdisp: 0x%s" % to_x(insn.disp))
# print displacement offset (offset into instruction bytes)
if insn.encoding.disp_offset != 0:
print("\tdisp_offset: 0x%x" % (insn.encoding.disp_offset))
# print displacement size
if insn.encoding.disp_size != 0:
print("\tdisp_size: 0x%x" % (insn.encoding.disp_size))
# SIB is not available in 16-bit mode
if (mode & CS_MODE_16 == 0):
# print SIB byte
print("\tsib: 0x%x" % (insn.sib))
if (insn.sib):
if insn.sib_base != 0:
print("\t\tsib_base: %s" % (insn.reg_name(insn.sib_base)))
if insn.sib_index != 0:
print("\t\tsib_index: %s" % (insn.reg_name(insn.sib_index)))
if insn.sib_scale != 0:
print("\t\tsib_scale: %d" % (insn.sib_scale))
# XOP CC type
if insn.xop_cc != X86_XOP_CC_INVALID:
print("\txop_cc: %u" % (insn.xop_cc))
# SSE CC type
if insn.sse_cc != X86_SSE_CC_INVALID:
print("\tsse_cc: %u" % (insn.sse_cc))
# AVX CC type
if insn.avx_cc != X86_AVX_CC_INVALID:
print("\tavx_cc: %u" % (insn.avx_cc))
# AVX Suppress All Exception
if insn.avx_sae:
print("\tavx_sae: TRUE")
# AVX Rounding Mode type
if insn.avx_rm != X86_AVX_RM_INVALID:
print("\tavx_rm: %u" % (insn.avx_rm))
count = insn.op_count(X86_OP_IMM)
if count > 0:
print("\timm_count: %u" % count)
for i in range(count):
op = insn.op_find(X86_OP_IMM, i + 1)
print("\t\timms[%u]: 0x%s" % (i + 1, to_x(op.imm)))
if insn.encoding.imm_offset != 0:
print("\timm_offset: 0x%x" % (insn.encoding.imm_offset))
if insn.encoding.imm_size != 0:
print("\timm_size: 0x%x" % (insn.encoding.imm_size))
if len(insn.operands) > 0:
print("\top_count: %u" % len(insn.operands))
c = -1
for i in insn.operands:
c += 1
if i.type == X86_OP_REG:
print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
if i.type == X86_OP_IMM:
print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x(i.imm)))
if i.type == X86_OP_MEM:
print("\t\toperands[%u].type: MEM" % c)
if i.mem.segment != 0:
print("\t\t\toperands[%u].mem.segment: REG = %s" % (c, insn.reg_name(i.mem.segment)))
if i.mem.base != 0:
print("\t\t\toperands[%u].mem.base: REG = %s" % (c, insn.reg_name(i.mem.base)))
if i.mem.index != 0:
print("\t\t\toperands[%u].mem.index: REG = %s" % (c, insn.reg_name(i.mem.index)))
if i.mem.scale != 1:
print("\t\t\toperands[%u].mem.scale: %u" % (c, i.mem.scale))
if i.mem.disp != 0:
print("\t\t\toperands[%u].mem.disp: 0x%s" % (c, to_x(i.mem.disp)))
# AVX broadcast type
if i.avx_bcast != X86_AVX_BCAST_INVALID:
print("\t\toperands[%u].avx_bcast: %u" % (c, i.avx_bcast))
# AVX zero opmask {z}
if i.avx_zero_opmask:
print("\t\toperands[%u].avx_zero_opmask: TRUE" % (c))
print("\t\toperands[%u].size: %u" % (c, i.size))
if i.access == CS_AC_READ:
print("\t\toperands[%u].access: READ" % (c))
elif i.access == CS_AC_WRITE:
print("\t\toperands[%u].access: WRITE" % (c))
elif i.access == CS_AC_READ | CS_AC_WRITE:
print("\t\toperands[%u].access: READ | WRITE" % (c))
(regs_read, regs_write) = insn.regs_access()
if len(regs_read) > 0:
print("\tRegisters read:", end="")
for r in regs_read:
print(" %s" %(insn.reg_name(r)), end="")
print("")
if len(regs_write) > 0:
print("\tRegisters modified:", end="")
for r in regs_write:
print(" %s" %(insn.reg_name(r)), end="")
print("")
if insn.eflags or insn.fpu_flags:
updated_flags = []
for group in insn.groups:
if group == X86_GRP_FPU:
for i in range(64):
if insn.fpu_flags & (1 << i):
updated_flags.append(get_fpu_flag_name(1 << i))
print("\tFPU_FLAGS: %s" % (' '.join(p for p in updated_flags)))
break
if not updated_flags:
for i in range(64):
if insn.eflags & (1 << i):
updated_flags.append(get_eflag_name(1 << i))
print("\tEFLAGS: %s" % (' '.join(p for p in updated_flags)))
# ## Test class Cs
def test_class():
for (arch, mode, code, comment, syntax) in all_tests:
print("*" * 16)
print("Platform: %s" % comment)
print("Code: %s" % to_hex(code))
print("Disasm:")
try:
md = Cs(arch, mode)
md.detail = True
if syntax is not None:
md.syntax = syntax
for insn in md.disasm(code, 0x1000):
print_insn_detail(mode, insn)
print ()
print ("0x%x:\n" % (insn.address + insn.size))
except CsError as e:
print("ERROR: %s" % e)
if __name__ == '__main__':
test_class()

View File

@ -1,70 +0,0 @@
#!/usr/bin/env python3
# Capstone Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
from capstone import *
from capstone.xcore import *
from xprint import to_x, to_hex
XCORE_CODE = b"\xfe\x0f\xfe\x17\x13\x17\xc6\xfe\xec\x17\x97\xf8\xec\x4f\x1f\xfd\xec\x37\x07\xf2\x45\x5b\xf9\xfa\x02\x06\x1b\x10\x09\xfd\xec\xa7"
all_tests = (
(CS_ARCH_XCORE, 0, XCORE_CODE, "XCore"),
)
def print_insn_detail(insn):
# print address, mnemonic and operands
print("0x%x:\t%s\t%s" % (insn.address, insn.mnemonic, insn.op_str))
# "data" instruction generated by SKIPDATA option has no detail
if insn.id == 0:
return
if len(insn.operands) > 0:
print("\top_count: %u" % len(insn.operands))
c = 0
for i in insn.operands:
if i.type == XCORE_OP_REG:
print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
if i.type == XCORE_OP_IMM:
print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x(i.imm)))
if i.type == XCORE_OP_MEM:
print("\t\toperands[%u].type: MEM" % c)
if i.mem.base != 0:
print("\t\t\toperands[%u].mem.base: REG = %s" \
% (c, insn.reg_name(i.mem.base)))
if i.mem.index != 0:
print("\t\t\toperands[%u].mem.index: REG = %s" \
% (c, insn.reg_name(i.mem.index)))
if i.mem.disp != 0:
print("\t\t\toperands[%u].mem.disp: 0x%s" \
% (c, to_x(i.mem.disp)))
if i.mem.direct != 1:
print("\t\t\toperands[%u].mem.direct: -1" % c)
c += 1
# ## Test class Cs
def test_class():
for (arch, mode, code, comment) in all_tests:
print("*" * 16)
print("Platform: %s" %comment)
print("Code: %s" % to_hex(code))
print("Disasm:")
try:
md = Cs(arch, mode)
md.detail = True
for insn in md.disasm(code, 0x1000):
print_insn_detail(insn)
print ()
print("0x%x:\n" % (insn.address + insn.size))
except CsError as e:
print("ERROR: %s" %e)
if __name__ == '__main__':
test_class()

View File

@ -1,5 +1,5 @@
# This file contains all customized compile options for Capstone.
# Consult COMPILE.TXT & docs/README for details.
# Consult COMPILE_MAKE.TXT & docs/README for details.
################################################################################
# Specify which archs you want to compile in. By default, we build all archs.

5
cs.c
View File

@ -1110,9 +1110,8 @@ cs_err CAPSTONE_API cs_option(csh ud, cs_opt_type type, size_t value)
}
break;
case CS_OPT_NO_BRANCH_OFFSET:
if (handle->PrintBranchImmNotAsAddress)
return CS_ERR_OK;
break;
handle->PrintBranchImmNotAsAddress = value == CS_OPT_ON ? true : false;
return CS_ERR_OK;
}
if (!arch_configs[handle->arch].arch_option)

View File

@ -66,14 +66,14 @@ void print_insn_detail_aarch64(csh handle, cs_insn *ins)
printf("\t\toperands[%u].sme.tile: %s\n", i, cs_reg_name(handle, op->sme.tile));
if (op->sme.slice_reg != AARCH64_REG_INVALID)
printf("\t\toperands[%u].sme.slice_reg: %s\n", i, cs_reg_name(handle, op->sme.slice_reg));
if (op->sme.slice_offset.imm != -1 || op->sme.slice_offset.imm_range.first != -1) {
if (op->sme.slice_offset.imm != AARCH64_SLICE_IMM_INVALID || op->sme.slice_offset.imm_range.first != AARCH64_SLICE_IMM_RANGE_INVALID) {
printf("\t\toperands[%u].sme.slice_offset: ", i);
if (op->sme.has_range_offset)
printf("%hhd:%hhd\n", op->sme.slice_offset.imm_range.first, op->sme.slice_offset.imm_range.offset);
else
printf("%d\n", op->sme.slice_offset.imm);
}
if (op->sme.slice_reg != AARCH64_REG_INVALID || op->sme.slice_offset.imm != -1)
if (op->sme.slice_reg != AARCH64_REG_INVALID || op->sme.slice_offset.imm != AARCH64_SLICE_IMM_INVALID)
printf("\t\toperands[%u].sme.is_vertical: %s\n", i, (op->sme.is_vertical ? "true" : "false"));
break;
case AARCH64_OP_PRED:

View File

@ -1965,7 +1965,7 @@ typedef enum {
// clang-format on
// generated content <AArch64GenCSSystemOperandsEnum.inc:GET_ENUM_VALUES_TSB> end
AArch64_TSB_ENDING,
AARCH64_TSB_ENDING,
} aarch64_tsb;
typedef union {
@ -2788,9 +2788,12 @@ typedef enum {
AARCH64_SME_OP_TILE_VEC, ///< SME operand is a tile indexed by a register and/or immediate
} aarch64_sme_op_type;
#define AARCH64_SLICE_IMM_INVALID UINT16_MAX
#define AARCH64_SLICE_IMM_RANGE_INVALID UINT8_MAX
typedef struct {
int8_t first;
int8_t offset;
uint8_t first;
uint8_t offset;
} aarch64_imm_range;
/// SME Instruction's matrix operand
@ -2799,9 +2802,9 @@ typedef struct {
aarch64_reg tile; ///< Matrix tile register
aarch64_reg slice_reg; ///< slice index reg
union {
int8_t imm;
aarch64_imm_range imm_range;
} slice_offset; ///< slice index offset. Is set to -1 if invalid.
uint16_t imm; ///< Invalid if equal to AARCH64_SLICE_IMM_INVALID
aarch64_imm_range imm_range; ///< Members are set to AARCH64_SLICE_IMM_RANGE_INVALID if invalid.
} slice_offset; ///< slice index offset.
bool has_range_offset; ///< If true, the offset is a range.
bool is_vertical; ///< Flag if slice is vertical or horizontal
} aarch64_op_sme;

View File

@ -903,7 +903,7 @@ typedef struct cs_arm {
ARMVCC_VPTCodes vcc; ///< Vector conditional code for this instruction.
bool update_flags; ///< does this insn update flags?
bool post_index; ///< only set if writeback is 'True', if 'False' pre-index, otherwise post.
int /* arm_mem_bo_opt */ mem_barrier; ///< Option for some memory barrier instructions
arm_mem_bo_opt mem_barrier; ///< Option for some memory barrier instructions
// Check ARM_PredBlockMask for encoding details.
uint8_t /* ARM_PredBlockMask */ pred_mask; ///< Used by IT/VPT block instructions.
/// Number of operands of this instruction,

View File

@ -1863,7 +1863,7 @@ typedef enum {
ARM64_TSB_CSYNC = AARCH64_TSB_CSYNC,
ARM64_TSB_ENDING = AArch64_TSB_ENDING,
ARM64_TSB_ENDING = AARCH64_TSB_ENDING,
} arm64_tsb;
typedef aarch64_sysop_reg arm64_sysop_reg;

View File

@ -284,7 +284,7 @@ typedef enum cs_opt_type {
CS_OPT_SKIPDATA_SETUP, ///< Setup user-defined function for SKIPDATA option
CS_OPT_MNEMONIC, ///< Customize instruction mnemonic
CS_OPT_UNSIGNED, ///< print immediate operands in unsigned form
CS_OPT_NO_BRANCH_OFFSET, ///< ARM, prints branch immediates without offset.
CS_OPT_NO_BRANCH_OFFSET, ///< ARM, PPC, AArch64, prints branch immediates without offset.
} cs_opt_type;
/// Runtime option value (associated with option type above)
@ -302,6 +302,12 @@ typedef enum cs_opt_value {
CS_OPT_DETAIL_REAL = 1 << 1, ///< If enabled, always sets the real instruction detail. Even if the instruction is an alias.
} cs_opt_value;
/// An option
typedef struct {
cs_opt_type type; ///< The option type
cs_opt_value val; ///< The option value to set.
} cs_opt;
/// Common instruction groups - to be consistent across all architectures.
typedef enum cs_group_type {
CS_GRP_INVALID = 0, ///< uninitialized/invalid group.

View File

@ -3280,6 +3280,8 @@ typedef enum ppc_insn_group {
/// PPC instruction formats. To get details about them please
/// refer to `PPCInstrFormats.td` in LLVM.
typedef enum {
PPC_INSN_FORM_INVALID = 0,
// generated content <PPCGenCSInsnFormatsEnum.inc> begin
// clang-format off

View File

@ -64,6 +64,8 @@ typedef enum sparc_hint {
SPARC_HINT_A = 1 << 0, ///< annul delay slot instruction
SPARC_HINT_PT = 1 << 1, ///< branch taken
SPARC_HINT_PN = 1 << 2, ///< branch NOT taken
SPARC_HINT_A_PN = SPARC_HINT_A | SPARC_HINT_PN,
SPARC_HINT_A_PT = SPARC_HINT_A | SPARC_HINT_PT,
} sparc_hint;
/// Operand type for instruction's operands

View File

@ -246,6 +246,7 @@ typedef enum x86_avx_rm {
/// Instruction prefixes - to be used in cs_x86.prefix[]
typedef enum x86_prefix {
X86_PREFIX_0 = 0x0,
X86_PREFIX_LOCK = 0xf0, ///< lock (cs_x86.prefix[0]
X86_PREFIX_REP = 0xf3, ///< rep (cs_x86.prefix[0]
X86_PREFIX_REPE = 0xf3, ///< repe/repz (cs_x86.prefix[0]

View File

@ -18,10 +18,12 @@ BUILD_PATH="$1"
check_list="clang-analyzer-*,-clang-analyzer-cplusplus*,-clang-analyzer-optin.performance.Padding"
if $(hash clang-tidy-15); then
clang-tidy-15 $(find ./arch ./*.c -type f -iregex ".*\.[c]") -p "$BUILD_PATH" -checks="$check_list" > ct-warnings.txt
if $(hash clang-tidy-18); then
echo -e "#############\nProduced by\n$(clang-tidy-18 --version)\n#############\n\n" > ct-warnings.txt
clang-tidy-18 $(find ./arch ./*.c -type f -iregex ".*\.[c]") -p "$BUILD_PATH" -checks="$check_list" >> ct-warnings.txt
else
clang-tidy $(find ./arch ./*.c -type f -iregex ".*\.[c]") -p "$BUILD_PATH" -checks="$check_list" > ct-warnings.txt
echo -e "#############\nProduced by\n$(clang-tidy --version)\n#############\n\n" > ct-warnings.txt
clang-tidy $(find ./arch ./*.c -type f -iregex ".*\.[c]") -p "$BUILD_PATH" -checks="$check_list" >> ct-warnings.txt
fi
if [ $? -ne 0 ]; then

View File

@ -1,47 +0,0 @@
## Input files for testing Capstone engine.
Input files used to test instructions of architectures and modes.
The test cases are taken from `llvm/test/MC`. Note that most of the LLVM tests
are for **encoding** of instructions (`asm_string -> bytes`).
We test the decoding (`bytes -> asm_string`).
A few tests might decode to a different asm string than
used to encode the instruction (because the behavior
of instructions can be equivalent).
Fix the obvious broken tests first and test the rest
against `llvm-objdump`.
### Update test files
Check `suite/auto-sync/README.md`
### Test file formatting
**Format of input files:**
```
# ARCH, MODE, OPTION
hexcode = assembly
```
**Example**
```
# CS_ARCH_ARM, CS_MODE_ARM+CS_MODE_V8, None
0xa0,0x0b,0x71,0xee = vadd.f64 d16, d17, d16
...
```
**Format of issue file:**
```
!# ARCH, MODE, OPTION
hexcode = assembly | regs_read | regs_read_count | regs_write | regs_write_count | groups | groups_count
```
**Example**
```
!# CS_ARCH_ARM64, CS_MODE_ARM, CS_OPT_DETAIL
0xc0,0x1e,0x0c,0x4e == mov v0.s[1], w22 ; operands[0].vas: 0xb ; operands[0].vector_index: 1
...
```

19
suite/MC/README.md Normal file
View File

@ -0,0 +1,19 @@
# Input files for fuzzing input
These files were the legacy test files but replaced.
No it only is consumed by `test_corpus3.py` to generate input cases for the fuzzer.
### Test file formatting
**Format of input files:**
```
# ARCH, MODE, OPTION
<hexcode> = <assembly-text>
```
**Example**
```
# CS_ARCH_ARM, CS_MODE_ARM+CS_MODE_V8, None
0xa0,0x0b,0x71,0xee = vadd.f64 d16, d17, d16
...
```

View File

@ -2,20 +2,9 @@ This directory contains some tools used by developers of Capstone project.
Average users should ignore all the contents here.
- arm/
Test some ARM's special input.
- MC/
Input used to test various architectures & modes.
- benchmark.py
This script benchmarks Python binding by disassembling some random code.
- test_*.sh
Run all the tests and send the output to external file to be compared later.
This is useful when we want to verify if a commit (wrongly) changes
the disassemble result.
- compile_all.sh
Compile Capstone for all platforms (*nix32, clang, cygwin, cross-compile) &
report the result as pass or fail.
@ -24,10 +13,6 @@ Average users should ignore all the contents here.
This simple script disassembles random code for all archs (or selected arch)
in order to find segfaults.
- test_mc.sh
This script compares the output of Capstone with LLVM's llvm-mc with the
input coming from MC/. This relies on test_mc.py to do all the hard works.
- x86odd.py
Test some tricky X86 instructions.

View File

@ -1,12 +0,0 @@
# Sample Makefile for Capstone Disassembly Engine
LIBNAME = capstone
test_arm_regression: test_arm_regression.o
${CC} $< -O3 -Wall -l$(LIBNAME) -o $@
%.o: %.c
${CC} -c -I../../include $< -o $@
clean:
rm -rf *.o test_arm_regression

View File

@ -1,391 +0,0 @@
/* Capstone Disassembler Engine */
/* By David Hogarty, 2014 */
// the following must precede stdio (woo, thanks msft)
#if defined(_MSC_VER) && _MSC_VER < 1900
#define _CRT_SECURE_NO_WARNINGS
#define snprintf _snprintf
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <capstone/platform.h>
#include <capstone/capstone.h>
static csh handle;
struct platform {
cs_arch arch;
cs_mode mode;
unsigned char *code;
size_t size;
char *comment;
int syntax;
};
static char *hex_string(unsigned char *str, size_t len)
{
// returns a malloced string that has the hex version of the string in it
// null if failed to malloc
char *hex_out;
size_t i;
hex_out = (char *) malloc(len*2 + 1); // two ascii characters per input character, plus trailing null
if (!hex_out) { goto Exit; }
for (i = 0; i < len; ++i) {
snprintf(hex_out + (i * 2), 3, "%02x", str[i]);
}
hex_out[len*2] = 0; // trailing null
Exit:
return hex_out;
}
static void snprint_insn_detail(char * buf, size_t * cur, size_t * left, cs_insn *ins)
{
#define _this_printf(...) \
{ \
size_t used = 0; \
used = snprintf(buf + *cur, *left, __VA_ARGS__); \
*left -= used; \
*cur += used; \
}
cs_arm *arm;
int i;
// detail can be NULL on "data" instruction if SKIPDATA option is turned ON
if (ins->detail == NULL)
return;
arm = &(ins->detail->arm);
if (arm->op_count)
_this_printf("\top_count: %u\n", arm->op_count);
for (i = 0; i < arm->op_count; i++) {
cs_arm_op *op = &(arm->operands[i]);
switch((int)op->type) {
default:
break;
case ARM_OP_REG:
_this_printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg));
break;
case ARM_OP_IMM:
_this_printf("\t\toperands[%u].type: IMM = 0x%" PRIx64 "\n", i, op->imm);
break;
case ARM_OP_FP:
_this_printf("\t\toperands[%u].type: FP = %f\n", i, op->fp);
break;
case ARM_OP_MEM:
_this_printf("\t\toperands[%u].type: MEM\n", i);
if (op->mem.base != ARM_REG_INVALID)
_this_printf("\t\t\toperands[%u].mem.base: REG = %s\n",
i, cs_reg_name(handle, op->mem.base));
if (op->mem.index != ARM_REG_INVALID)
_this_printf("\t\t\toperands[%u].mem.index: REG = %s\n",
i, cs_reg_name(handle, op->mem.index));
if (op->mem.scale != 1)
_this_printf("\t\t\toperands[%u].mem.scale: %u\n", i, op->mem.scale);
if (op->mem.disp != 0)
_this_printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i, op->mem.disp);
break;
case ARM_OP_PIMM:
_this_printf("\t\toperands[%u].type: P-IMM = %" PRIu64 "\n", i, op->imm);
break;
case ARM_OP_CIMM:
_this_printf("\t\toperands[%u].type: C-IMM = %" PRIu64 "\n", i, op->imm);
break;
}
if (op->shift.type != ARM_SFT_INVALID && op->shift.value) {
if (op->shift.type < ARM_SFT_ASR_REG) {
// shift with constant value
_this_printf("\t\t\tShift: %u = %u\n", op->shift.type, op->shift.value);
} else {
// shift with register
_this_printf("\t\t\tShift: %u = %s\n", op->shift.type,
cs_reg_name(handle, op->shift.value));
}
}
}
if (arm->cc != ARMCC_AL && arm->cc != ARMCC_UNDEF) {
_this_printf("\tCode condition: %u\n", arm->cc);
}
if (arm->update_flags) {
_this_printf("\tUpdate-flags: True\n");
}
if (ins->detail->writeback) {
_this_printf("\tWrite-back: True\n");
}
#undef _this_printf
}
static void print_insn_detail(cs_insn *ins)
{
char a_buf[2048];
size_t cur=0, left=2048;
snprint_insn_detail(a_buf, &cur, &left, ins);
printf("%s\n", a_buf);
}
struct invalid_code {
unsigned char *code;
size_t size;
char *comment;
};
#define MAX_INVALID_CODES 16
struct invalid_instructions {
cs_arch arch;
cs_mode mode;
char *platform_comment;
int num_invalid_codes;
struct invalid_code invalid_codes[MAX_INVALID_CODES];
};
static void test_invalids()
{
struct invalid_instructions invalids[] = {{
CS_ARCH_ARM,
CS_MODE_THUMB,
"Thumb",
1,
{{
(unsigned char *)"\xbd\xe8\x1e\xff",
4,
"invalid thumb2 pop because sp used and because both pc and lr are "
"present at the same time"
}},
}};
struct invalid_instructions * invalid = NULL;
uint64_t address = 0x1000;
cs_insn *insn;
int i;
int j;
size_t count;
printf("\nShould be invalid\n"
"-----------------\n");
for (i = 0; i < sizeof(invalids)/sizeof(invalids[0]); i++) {
cs_err err;
invalid = invalids + i;
err = cs_open(invalid->arch, invalid->mode, &handle);
if (err) {
printf("Failed on cs_open() with error returned: %u\n", err);
continue;
}
cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_NOREGNAME);
for (j = 0; j < invalid->num_invalid_codes; ++j) {
struct invalid_code *invalid_code = NULL;
char *hex_str = NULL;
invalid_code = invalid->invalid_codes + j;
hex_str = hex_string(invalid_code->code, invalid_code->size);
printf("%s %s: %s\n", invalid->platform_comment, hex_str, invalid_code->comment);
free(hex_str);
count = cs_disasm(handle,
invalid_code->code, invalid_code->size, address, 0, &insn
);
if (count) {
size_t k;
printf(" ERROR:\n");
for (k = 0; k < count; k++) {
printf(" 0x%"PRIx64":\t%s\t%s\n",
insn[k].address, insn[k].mnemonic, insn[k].op_str);
print_insn_detail(&insn[k]);
}
cs_free(insn, count);
} else {
printf(" SUCCESS: invalid\n");
}
}
cs_close(&handle);
}
}
struct valid_code {
unsigned char *code;
size_t size;
uint32_t start_addr;
char *expected_out;
char *comment;
};
#define MAX_VALID_CODES 16
struct valid_instructions {
cs_arch arch;
cs_mode mode;
char *platform_comment;
int num_valid_codes;
struct valid_code valid_codes[MAX_VALID_CODES];
};
static void test_valids()
{
struct valid_instructions valids[] = {{
CS_ARCH_ARM,
CS_MODE_THUMB,
"Thumb",
3,
{{ (unsigned char *)"\x00\xf0\x26\xe8", 4, 0x352,
"0x352:\tblx\t#0x3a0\n"
"\top_count: 1\n"
"\t\toperands[0].type: IMM = 0x3a0\n",
"thumb2 blx with misaligned immediate"
}, { (unsigned char *)"\x05\xdd", 2, 0x1f0,
"0x1f0:\tble\t#0x1fe\n"
"\top_count: 1\n"
"\t\toperands[0].type: IMM = 0x1fe\n"
"\tCode condition: 14\n",
"thumb b cc with thumb-aligned target"
}, { (unsigned char *)"\xbd\xe8\xf0\x8f", 4, 0,
"0x0:\tpop.w\t{r4, r5, r6, r7, r8, r9, r10, r11, pc}\n"
"\top_count: 9\n"
"\t\toperands[0].type: REG = r4\n"
"\t\toperands[1].type: REG = r5\n"
"\t\toperands[2].type: REG = r6\n"
"\t\toperands[3].type: REG = r7\n"
"\t\toperands[4].type: REG = r8\n"
"\t\toperands[5].type: REG = r9\n"
"\t\toperands[6].type: REG = r10\n"
"\t\toperands[7].type: REG = r11\n"
"\t\toperands[8].type: REG = pc\n",
"thumb2 pop that should be valid"
},
}
}};
struct valid_instructions *valid = NULL;
cs_insn *insn;
int i;
int j;
size_t count;
for (i = 0; i < sizeof(valids)/sizeof(valids[0]); i++) {
cs_err err;
valid = valids + i;
err = cs_open(valid->arch, valid->mode, &handle);
if (err) {
printf("Failed on cs_open() with error returned: %u\n", err);
continue;
}
cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_NOREGNAME);
#define _this_printf(...) \
{ \
size_t used = 0; \
used = snprintf(tmp_buf + cur, left, __VA_ARGS__); \
left -= used; \
cur += used; \
}
printf("\nShould be valid\n"
"---------------\n");
for (j = 0; j < valid->num_valid_codes; ++j) {
char tmp_buf[2048];
size_t left = 2048;
size_t cur = 0;
char * hex_str = NULL;
struct valid_code * valid_code = NULL;
valid_code = valid->valid_codes + j;
hex_str = hex_string(valid_code->code, valid_code->size);
printf("%s %s @ 0x%04x: %s\n %s",
valid->platform_comment, hex_str, valid_code->start_addr,
valid_code->comment, valid_code->expected_out);
free(hex_str);
count = cs_disasm(handle,
valid_code->code, valid_code->size,
valid_code->start_addr, 0, &insn
);
if (count) {
size_t k;
size_t max_len = 0;
size_t tmp_len = 0;
for (k = 0; k < count; k++) {
_this_printf(
"0x%"PRIx64":\t%s\t%s\n",
insn[k].address, insn[k].mnemonic,
insn[k].op_str
);
snprint_insn_detail(tmp_buf, &cur, &left, &insn[k]);
}
max_len = strlen(tmp_buf);
tmp_len = strlen(valid_code->expected_out);
if (tmp_len > max_len) {
max_len = tmp_len;
}
if (memcmp(tmp_buf, valid_code->expected_out, max_len)) {
printf(
" ERROR: '''\n%s''' does not match"
" expected '''\n%s'''\n",
tmp_buf, valid_code->expected_out
);
} else {
printf(" SUCCESS: valid\n");
}
cs_free(insn, count);
} else {
printf("ERROR: invalid\n");
}
}
cs_close(&handle);
}
#undef _this_prinf
}
int main()
{
test_invalids();
test_valids();
return 0;
}

View File

@ -4,4 +4,9 @@ vendor/llvm_root
src/auto-sync/config.json
src/autosync/cpptranslator/Tests/Differ/test_saved_patches.json
src/autosync.egg-info
src/autosync/Tests/MCUpdaterTests/ARCH/Output
src/autosync/Tests/MCUpdaterTests/Disassembler/ARCH/Output
src/autosync/lit_config/test_dir_*
src/autosync/lit_config/.lit_test_times.txt
src/autosync/Tests/MCUpdaterTests/test_output
src/autosync/Tests/MCUpdaterTests/ARCH/Output

View File

@ -15,7 +15,7 @@ Please refer to [intro.md](intro.md) for an introduction about this tool.
## Install
Setup Python environment and Tree-sitter
#### Setup Python environment and Tree-sitter
```
cd <root-dir-Capstone>
@ -26,13 +26,35 @@ python3 -m venv ./.venv
source ./.venv/bin/activate
```
Install Auto-Sync framework
#### Install Auto-Sync framework
```
cd suite/auto-sync/
pip install -e .
```
#### Clone Capstones LLVM fork and build `llvm-tblgen`
```bash
git clone https://github.com/capstone-engine/llvm-capstone vendor/llvm_root/
cd llvm-capstone
git checkout auto-sync
mkdir build
cd build
# You can also build the "Release" version
cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug ../llvm
cmake --build . --target llvm-tblgen --config Debug
cd ../../
```
#### Install `llvm-mc` and `FileCheck`
Additionally, we need `llvm-mc` and `FileCheck` to generate our regression tests.
You can build it, but it will take a lot of space on your hard drive.
You can also get the binaries [here](https://releases.llvm.org/download.html) or
install it with your package manager (usually something like `llvm-18-dev`).
Just ensure it is in your `PATH` as `llvm-mc` and `FileCheck` (not as `llvm-mc-18` or similar though!).
## Architecture
Please read [ARCHITECTURE.md](https://github.com/capstone-engine/capstone/blob/next/docs/ARCHITECTURE.md) to understand how Auto-Sync works.
@ -50,20 +72,6 @@ Check if your architecture is supported.
./src/autosync/ASUpdater.py -h
```
Clone Capstones LLVM fork and build `llvm-tblgen`
```
git clone https://github.com/capstone-engine/llvm-capstone vendor/llvm_root/
cd llvm-capstone
git checkout auto-sync
mkdir build
cd build
# You can also build the "Release" version
cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug ../llvm
cmake --build . --target llvm-tblgen --config Debug
cd ../../
```
Run the updater
```

View File

@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 3.15)
set(AUTO_SYNC_C_TEST_SRC_DIR ${AUTO_SYNC_C_TEST_DIR}/src)
set(AUTO_SYNC_C_TEST_INC_DIR ${AUTO_SYNC_C_TEST_DIR}/include)
include_directories(${AUTO_SYNC_C_TEST_INC_DIR} ${PROJECT_SOURCE_DIR}/include)
file(GLOB AUTO_SYNC_C_SRC ${AUTO_SYNC_C_TEST_SRC_DIR}/*.c)
add_executable(compat_header_build_test ${AUTO_SYNC_C_SRC})
add_dependencies(compat_header_build_test capstone)
target_link_libraries(compat_header_build_test PUBLIC capstone)
add_test(NAME ASCompatibilityHeaderTest
COMMAND compat_header_build_test
WORKING_DIRECTORY ${AUTO_SYNC_C_TEST_DIR}
)

View File

@ -12,7 +12,7 @@ int main(void)
csh handle;
if (cs_open(CS_ARCH_ARM64, CS_MODE_BIG_ENDIAN, &handle) != CS_ERR_OK) {
printf("cs_open failed\n");
fprintf(stderr, "cs_open failed\n");
return -1;
}
@ -20,21 +20,48 @@ int main(void)
cs_insn *insn;
uint8_t bytes[] = "0x1a,0x48,0xa0,0xf8";
size_t count = cs_disasm(handle, bytes, sizeof(bytes), 0x1000, 1, &insn);
if (count > 0) {
printf("0x%" PRIx64 ":\t%s\t\t%s\n", insn[0].address,
insn[0].mnemonic, insn[0].op_str);
printf("A register = %s\n", cs_reg_name(handle, insn[0].detail->arm64.operands[0].reg));
printf("An imm = 0x%" PRIx64 "\n", insn[0].detail->arm64.operands[1].imm);
size_t count =
cs_disasm(handle, bytes, sizeof(bytes), 0x1000, 1, &insn);
if (count != 1) {
fprintf(stderr, "Failed to disassemble code.\n");
goto err;
}
printf("0x%" PRIx64 ":\t%s\t\t%s\n", insn[0].address, insn[0].mnemonic,
insn[0].op_str);
printf("A register = %s\n",
cs_reg_name(handle, insn[0].detail->arm64.operands[0].reg));
printf("An imm = 0x%" PRIx64 "\n",
insn[0].detail->arm64.operands[1].imm);
cs_free(insn, count);
} else {
printf("ERROR: Failed to disassemble given code!\n");
cs_close(&handle);
return -1;
if (insn[0].address != 0x1000) {
fprintf(stderr, "Address wrong.\n");
goto err;
}
if (strcmp(insn[0].mnemonic, "adr") != 0) {
fprintf(stderr, "Mnemonic wrong.\n");
goto err;
}
if (strcmp(insn[0].op_str, "x1, 0xf162d") != 0) {
fprintf(stderr, "op_str wrong.\n");
goto err;
}
if (strcmp(cs_reg_name(handle, insn[0].detail->arm64.operands[0].reg),
"x1") != 0) {
fprintf(stderr, "register wrong.\n");
goto err;
}
if (insn[0].detail->arm64.operands[1].imm != 0xf162d) {
fprintf(stderr, "Immediate wrong.\n");
goto err;
}
cs_free(insn, count);
cs_close(&handle);
return 0;
err:
printf("ERROR: Failed to disassemble given code corrcetly!\n");
cs_free(insn, count);
cs_close(&handle);
return -1;
}

View File

@ -1,3 +1,3 @@
#!/usr/bin/bash
python3.11 -m black src/autosync
python3 -m black src/autosync

View File

@ -7,15 +7,15 @@ name = "autosync"
version = "0.1.0"
dependencies = [
"termcolor >= 2.3.0",
"tree_sitter >= 0.21.3",
"tree_sitter == 0.22.3",
"tree-sitter-cpp >=0.22.0",
"black >= 24.3.0",
"usort >= 1.0.8",
"setuptools >= 69.2.0",
"ninja >= 1.11.1.1",
"cmake >= 3.28.3",
"reuse >= 3.0.1",
"clang-format >= 18.1.1",
"lit >= 18.1.8",
]
requires-python = ">= 3.11"

View File

@ -73,7 +73,11 @@ class ASUpdater:
self.inc_list,
)
self.mc_updater = MCUpdater(
self.arch, get_path("{LLVM_MC_TEST_DIR}"), None, None
self.arch,
get_path("{LLVM_MC_TEST_DIR}"),
None,
None,
True if self.arch == "ARM" else False,
)
def clean_build_dir(self) -> None:
@ -192,6 +196,7 @@ class ASUpdater:
log.info(f"Copied {i} files")
# MC tests
i = 0
mc_dir = get_path("{MC_DIR}").joinpath(self.arch)
log.info(f"Copy MC test files to {mc_dir}")
for file in get_path("{MCUPDATER_OUT_DIR}").iterdir():

View File

@ -34,8 +34,8 @@ def find_id_by_type(node: Node, node_types: [str], type_must_match: bool) -> byt
"""
Recursively searches for a node sequence with given node types.
A valid sequence is a path from !\f$node_n\f$ to !\f$node_{(n + |node\_types|-1)}\f$ where
!\f$\forall i \in \{0, ..., |node\_types|-1\}: type(node_{(n + i)}) = node\_types_i\f$.
A valid sequence is a path from node_n to node_{(n + |node_types|-1)} where
forall i in {0, ..., |node_types|-1}: type(node_{(n + i)}) = node_types_i.
If a node sequence is found, this functions returns the text associated with the
last node in the sequence.
@ -159,6 +159,11 @@ def get_path(config_path: str) -> Path:
return PathVarHandler().complete_path(config_path)
def test_only_overwrite_path_var(var_name: str, new_path: Path):
"""Don't use outside of testing."""
return PathVarHandler().test_only_overwrite_var(var_name, new_path)
def fail_exit(msg: str) -> None:
"""Logs a fatal message and exits with error code 1."""
log.fatal(msg)

View File

@ -1,386 +1,448 @@
#!/usr/bin/env python3
# Copyright © 2024 Rot127 <unisono@quyllur.org>
# SPDX-License-Identifier: BSD-3
import argparse
import logging as log
import json
import re
import sys
from enum import Enum
import subprocess as sp
from pathlib import Path
from autosync.Targets import TARGETS_LLVM_NAMING
from autosync.Helper import convert_loglevel, get_path
# The CHECK prefix for tests.
VALID_PREFIX = r"(CHECK(-NEXT)?|FP[A-Z0-9]+)"
CHECK = rf"((#|//)\s*{VALID_PREFIX}:)"
ASM = r"(?P<asm_text>[^/@]+)"
ENC = r"(\[?(?P<enc_bytes>((0x[a-fA-F0-9]{1,2}[, ]{0,2}))+)[^, ]?\]?)"
match_patterns = {
# A commented encoding with only CHECK or something similar in front of it, skip it.
"skip_pattern": (
rf"(^((#|//)\s*[-A-Z0-9]+):\s*{ENC}\s*$)|" r"(warning: .*)|" r"((#\s+)?NO.+)"
),
# The encoding bytes pattern is in every file the same.
# But the disassembler and assembler tests pre-fix them differently.
# This is only the pattern for the encoding bytes. Without any prefix.
#
# The bytes are encoded with `0x` prefix and every byte is separated with a `,` or ` `.
# Optionally, they are enclosed in `[0x10,...]` brackets.
# E.g.: `[0x01,0xaa,0xb1,0x81]` or `0x01,0xaa,0xb1,0x81`.
# In the disassembler tests they don't have any prefix.
# In assembler tests they might have different prefixes like `CHECK-ENCODING`
# The matched bytes can be accessed from the group "enc_bytes"
"enc_bytes": ENC,
# Encodings in disassembly tests can have several prefixes
"enc_prefix_disas":
# start of line with CHECK: ... prefix
r"((^\s*)|"
# start of line with `CHECK: ...` prefix and the encoding after the asm text.
rf"({CHECK}.+encoding:\s+))",
# The asm checking line for `MC/Disassembler/*` tests follows the pattern:
# `# CHECK: <asm-text>`
# Usually multiple 'CHECK' come before or after the encoding bytes.
# Meaning: first comes a block of `# CHECK: ...` and afterwards for every `# CHECK: ...`
# line the encoding bytes.
# And wise versa, with the encoding bytes first and afterwards the asm text checks.
# The matched asm text can be accessed from the group "asm_text"
"asm_check": rf"{CHECK}\s+{ASM}(\s*(#|//)\s+encoding:\s+{ENC})?",
# Single line disassembly test
"single_line_disas": rf"^{ENC}\s+#\s+{ASM}",
# The RUN line, with the command to run the test file, contains sometimes the `mattr` flags.
# These are relevant, because they enable or disable features we might need to
# respect in our tests as well.
# The matched `mattr` cmd line option (if any) can be accessed from the group `mattr`
"run_line": r"RUN:.*(?P<mattr>mattr=[^ ]+).+",
}
class LLVM_MC_Command:
def __init__(self, cmd_line: str, mattr: str):
self.cmd: str = ""
self.opts: str = ""
self.file: Path | None = None
self.mattr: str = mattr
self.cmd, self.opts, self.file = self.parse_llvm_mc_line(cmd_line)
if not (self.cmd and self.opts and self.file):
log.warning(f"Could not parse llvm-mc command: {cmd_line}")
elif not "--show-encoding" in self.cmd:
self.cmd = re.sub("llvm-mc", "llvm-mc --show-encoding", self.cmd)
def parse_llvm_mc_line(self, line: str) -> tuple[str, str, Path]:
test_file_base_dir = str(get_path("{LLVM_LIT_TEST_DIR}").absolute())
file = re.findall(rf"{test_file_base_dir}\S+", line)
if not file:
log.warning(f"llvm-mc command doesn't contain a file: {line}")
return None, None, None
test_file = file[0]
cmd = re.sub(rf"{test_file}", "", line).strip()
cmd = re.sub(r"\s+", " ", cmd)
arch = re.finditer(r"(triple|arch)[=\s](\S+)", cmd)
mattr = re.finditer(r"(mattr|mcpu)[=\s](\S+)", cmd)
opts = ",".join([m.group(2) for m in arch]) if arch else ""
if mattr:
opts += "" if not opts else ","
opts += ",".join([m.group(2).strip("+") for m in mattr])
return cmd, opts, Path(test_file)
def exec(self) -> sp.CompletedProcess:
with open(self.file, "b+r") as f:
content = f.read()
if self.mattr:
# If mattr exists, patch it into the cmd
if "mattr" in self.cmd:
self.cmd = re.sub(
r"mattr[=\s]+", f"mattr={self.mattr} -mattr=", self.cmd
)
else:
self.cmd = re.sub(r"llvm-mc", f"llvm-mc -mattr={self.mattr}", self.cmd)
log.debug(f"Run: {self.cmd}")
result = sp.run(self.cmd.split(" "), input=content, capture_output=True)
return result
def get_opts_list(self) -> list[str]:
opts = self.opts.strip().strip(",")
opts = re.sub(r"[, ]+", ",", opts)
return opts.split(",")
def __str__(self) -> str:
return f"{self.cmd} < {str(self.file.absolute())}"
class Test:
def __init__(self, encoding: str | None, asm_text: str | None):
self.encoding: str | None = encoding
self.asm_text: str | None = asm_text
def __str__(self):
self.encoding.replace(" ", ",")
self.encoding = self.encoding.strip("[]")
return f"{self.encoding} == {self.asm_text}"
def test_complete(self) -> bool:
return self.encoding is not None and self.asm_text is not None
def add_missing(self, encoding: str | None, asm_text: str | None):
if encoding is None and asm_text is None:
raise ValueError("One of the arguments must be set.")
if not self.encoding:
if not encoding:
raise ValueError("Test still needs the encoding but it is None.")
self.encoding = encoding
if not self.asm_text:
if not asm_text:
raise ValueError("Test still needs the asm_text but it is None.")
self.asm_text = asm_text
class TestManager:
"""Class to manage incomplete tests. It automatically assigns the encoding and asm text
to the correct Test objects it holds.
It assumes that incomplete tests (only encoding OR the asm_text is given)
are all given in the same order.
Meaning: The first test without any asm_text but the encoding, is the same test
which is later given with only the asm_text but without encoding.
E.g.:
Order in which tests must be given to this Manager:
Test 1 -> (<encoding>, None)
Test 2 -> (<encoding>, None)
Test 3 -> (<encoding>, None)
...
Test 1 -> (None, <asm_text>)
Test 2 -> (None, <asm_text>)
Test 3 -> (None, <asm_text>)
...
class MCTest:
"""
A single test. It can contain multiple decoded instruction for a given byte sequence.
In general a MCTest always tests a sequence of instructions in a single .text segment.
"""
class AddingState(Enum):
ENCODING = 0
ASM_TEXT = 1
UNSET = 2
def __init__(self):
# If set, the already added tests are completed with the given information.
self.switched = False
self.state = self.AddingState.UNSET
# List of all tests which still miss a part.
self.incomplete_tests: list[Test] = list()
# Tests which are complete
self.completed: list[Test] = list()
def add_test(self, encoding: str | None, asm_text: str | None):
if encoding is not None and asm_text is not None:
if not (
self.state == self.AddingState.UNSET and len(self.incomplete_tests) == 0
):
log.debug(
f"Complete test found. Drop incomplete {len(self.incomplete_tests)} tests"
)
self.reset_incomplete()
self.state = self.AddingState.UNSET
self.completed.append(Test(encoding, asm_text))
return
if self.state == self.AddingState.UNSET:
assert len(self.incomplete_tests) == 0
# Add the first incomplete test
if encoding and asm_text:
self.state = self.AddingState.UNSET
elif encoding:
self.state = self.AddingState.ENCODING
else:
self.state = self.AddingState.ASM_TEXT
# Check if we complete the already added tests
if (self.state == self.AddingState.ENCODING and encoding is None) or (
self.state == self.AddingState.ASM_TEXT and asm_text is None
):
self.switched = True
oldstate = self.state
self.state = (
self.AddingState.ENCODING
if self.state == self.AddingState.ASM_TEXT
else self.AddingState.ASM_TEXT
)
log.debug(f"switch {oldstate} -> {self.state}")
if self.switched:
log.debug(f"Add incomplete II: {encoding} {asm_text}")
test = self.incomplete_tests.pop(0)
test.add_missing(encoding, asm_text)
self.completed.append(test)
def __init__(self, arch: str, opts: list[str], encoding: str, asm_text: str):
self.arch = arch
if arch.lower() in ["arm", "powerpc", "ppc", "aarch64"]:
# Arch and PPC require this option for MC tests.
self.opts = ["CS_OPT_NO_BRANCH_OFFSET"] + opts
else:
log.debug(f"Add incomplete I: {encoding} {asm_text}")
self.incomplete_tests.append(Test(encoding, asm_text))
self.opts = opts
self.encoding: list[str] = [encoding]
self.asm_text: list[str] = [asm_text]
# Lastly check if we can reset.
if len(self.incomplete_tests) == 0:
# All tests are completed. Reset
self.state = self.AddingState.UNSET
self.switched = False
log.debug(f"Reset: {self.state}")
def extend(self, encoding: str, asm_text: str):
self.encoding.append(encoding)
self.asm_text.append(asm_text)
def check_all_complete(self) -> bool:
if len(self.incomplete_tests) != 0:
log.debug(f"We have {len(self.incomplete_tests)} incomplete tests.")
return False
return True
def get_completed(self) -> list[Test]:
return self.completed
def get_stats(self) -> str:
return (
f"completed: {len(self.completed)} incomplete: {len(self.incomplete_tests)}"
def __str__(self):
encoding = ",".join(self.encoding)
encoding = re.sub(r"[\[\]]", "", encoding)
encoding = encoding.strip()
encoding = re.sub(r"[\s,]+", ", ", encoding)
yaml_tc = (
" -\n"
" input:\n"
" bytes: [ <ENCODING> ]\n"
' arch: "<ARCH>"\n'
" options: [ <OPTIONS> ]\n"
" expected:\n"
" insns:\n"
)
template = " -\n asm_text: <ASM_TEXT>\n"
insn_cases = ""
for text in self.asm_text:
insn_cases += template.replace("<ASM_TEXT>", f'"{text}"')
def get_num_completed(self) -> int:
return len(self.completed)
def get_num_incomplete(self) -> int:
return len(self.incomplete_tests)
def reset_incomplete(self):
self.incomplete_tests.clear()
self.state = self.AddingState.UNSET
self.switched = False
yaml_tc = yaml_tc.replace("<ENCODING>", encoding)
yaml_tc = yaml_tc.replace("<ARCH>", f"CS_ARCH_{self.arch.upper()}")
yaml_tc = yaml_tc.replace("<OPTIONS>", ", ".join([f'"{o}"' for o in self.opts]))
yaml_tc += insn_cases
return yaml_tc
class TestFile:
def __init__(
self, arch: str, filename: str, manager: TestManager, mattrs: list[str] | None
self,
arch: str,
file_path: Path,
opts: list[str] | None,
mc_cmd: LLVM_MC_Command,
unified_test_cases: bool,
):
self.arch = arch
self.filename = filename
self.manager = manager
self.mattrs: list[str] = list() if not mattrs else mattrs
self.tests = list()
self.arch: str = arch
self.file_path: Path = file_path
self.opts: list[str] = list() if not opts else opts
self.mc_cmd: LLVM_MC_Command = mc_cmd
# Indexed by .text section count
self.tests: dict[int : list[MCTest]] = dict()
def add_mattr(self, mattr: str):
if not self.mattrs:
self.mattrs = list()
if mattr not in self.mattrs:
self.mattrs.append(mattr)
self.init_tests(unified_test_cases)
def add_tests(self, tests: list[Test]):
self.tests = tests
def init_tests(self, unified_test_cases: bool):
mc_output = self.mc_cmd.exec()
if mc_output.stderr and not mc_output.stdout:
# We can still continue. We just ignore the failed cases.
log.debug(f"llvm-mc cmd stderr: {mc_output.stderr}")
log.debug(f"llvm-mc result: {mc_output}")
text_section = 0 # Counts the .text sections
asm_pat = f"(?P<asm_text>.+)"
enc_pat = r"(\[?(?P<full_enc_string>(?P<enc_bytes>((0x[a-fA-F0-9]{1,2}[, ]{0,2}))+)[^, ]?)\]?)"
for line in mc_output.stdout.splitlines():
line = line.decode("utf8")
if ".text" in line:
text_section += 1
continue
match = re.search(
rf"^\s*{asm_pat}\s*(#|//|@)\s*encoding:\s*{enc_pat}", line
)
if not match:
continue
full_enc_string = match.group("full_enc_string")
if not re.search(r"0x[a-fA-F0-9]{1,2}$", full_enc_string[:-1]):
log.debug(f"Ignore because symbol injection is needed: {line}")
# The encoding string contains symbol information of the form:
# [0xc0,0xe0,A,A,A... or similar. We ignore these for now.
continue
enc_bytes = match.group("enc_bytes").strip()
asm_text = match.group("asm_text").strip()
asm_text = re.sub(r"\t+", " ", asm_text)
asm_text = asm_text.strip()
if not self.valid_byte_seq(enc_bytes):
continue
if text_section in self.tests:
if unified_test_cases:
self.tests[text_section][0].extend(enc_bytes, asm_text)
else:
self.tests[text_section].append(
MCTest(self.arch, self.opts, enc_bytes, asm_text)
)
else:
self.tests[text_section] = [
MCTest(self.arch, self.opts, enc_bytes, asm_text)
]
def has_tests(self) -> bool:
return len(self.tests) != 0
def get_cs_testfile_content(self) -> str:
old_mc_test_file = get_path("{MC_DIR}").joinpath(
f"{self.arch}/{self.filename}.cs"
)
if not old_mc_test_file.exists():
header = (
f"# CS_ARCH_{self.arch.upper()}, None, None\n"
"# This regression test file is new. The option flags could not be determined.\n"
f"# LLVM uses the following mattr = {self.mattrs}"
)
else:
with open(old_mc_test_file) as f:
init_line = f.readlines()[0]
assert init_line != "" and "# CS_ARCH_" in init_line
header = init_line
content = header + "\n"
for test in self.tests:
content += f"{test}\n"
def get_cs_testfile_content(self, only_test: bool) -> str:
content = "\n" if only_test else "test_cases:\n"
for tl in self.tests.values():
content += "\n".join([str(t) for t in tl])
return content
def num_test_cases(self) -> int:
return len(self.tests)
def valid_byte_seq(self, enc_bytes):
match self.arch:
case "AArch64":
# It always needs 4 bytes.
# Otherwise it is likely a reloc or symbol test
return enc_bytes.count("0x") == 4
case _:
return True
def get_multi_mode_filename(self) -> Path:
filename = self.file_path.stem
parent = self.file_path.parent
detailed_name = f"{filename}_{'_'.join(self.opts)}.txt"
detailed_name = re.sub(r"[+-]", "_", detailed_name)
out_path = parent.joinpath(detailed_name)
return Path(out_path)
def get_simple_filename(self) -> Path:
return self.file_path
def __lt__(self, other) -> bool:
return str(self.file_path) < str(other.file_path)
class MCUpdater:
"""
The MCUpdater parses all test files of the LLVM MC regression tests.
Each of those LLVM files can contain several llvm-mc commands to run on the same file.
Mostly this is done to test the same file with different CPU features enabled.
So it can test different flavors of assembly etc.
In Capstone all modules enable always all CPU features (even if this is not
possible in reality).
Due to this we always parse all llvm-mc commands run on a test file, generate a TestFile
object for each of it, but only write the last one of them to disk.
Once https://github.com/capstone-engine/capstone/issues/1992 is resolved, we can
write all variants of a test file to disk.
This is already implemented and tested with multi_mode = True.
"""
def __init__(
self,
arch: str,
mc_dir: Path,
excluded: list[str] | None,
included: list[str] | None,
unified_test_cases: bool,
multi_mode: bool = False,
):
self.symbolic_links = list()
self.arch = arch
self.test_dir_link_prefix = f"test_dir_{arch}_"
self.mc_dir = mc_dir
self.excluded = excluded if excluded else list()
self.included = included if included else list()
self.test_files: dict[str:TestFile] = dict()
def parse_file(self, filepath: Path) -> TestFile | None:
"""Parse a MC test file and return it as an object with all tests found.
If it couldn't parse the file cleanly, it prints errors but returns it anyways.
"""
with open(filepath) as f:
lines = f.readlines()
test_file = TestFile(self.arch, filepath.name, TestManager(), None)
manager = test_file.manager
for line in lines:
if line == "\n":
# New line means new block starts. Drop all incomplete tests.
log.debug("New line. Drop all incomplete tests")
test_file.manager.reset_incomplete()
try:
if mattr := self.get_mattr(line):
test_file.add_mattr(mattr)
continue
encoding, asm_text = self.get_enc_asm(line)
if not encoding and not asm_text:
continue
manager.add_test(encoding, asm_text)
except ValueError as e:
raise e
log.debug(f"Failed to parse {test_file.filename}. Skipping it")
return None
manager.check_all_complete()
test_file.add_tests(manager.get_completed())
log.debug(f"Parsed {manager.get_num_completed()} tests:\t{filepath.name}")
return test_file
@staticmethod
def get_mattr(line: str) -> str | None:
match = re.search(match_patterns["run_line"], line)
if not match or not match.group("mattr"):
return None
return match.group("mattr")
@staticmethod
def get_enc_asm(line: str) -> tuple[str | None, str | None]:
enc: str | None = None
asm_text: str | None = None
if re.search(match_patterns["skip_pattern"], line):
return None, None
# Check for single line tests
single_match = re.search(match_patterns["single_line_disas"], line)
if single_match:
return (
single_match.group("enc_bytes"),
single_match.group("asm_text").strip(),
)
asm_match = re.search(match_patterns["asm_check"], line)
if asm_match:
asm_text = asm_match.group("asm_text")
if asm_match.group("enc_bytes"):
# Single line test
enc = asm_match.group("enc_bytes")
if asm_text:
asm_text = asm_text.strip()
# A single line test. Return the result
if asm_text and enc:
return enc, asm_text
# Check if the line contains at least encoding bytes
pattern = rf"{match_patterns['enc_prefix_disas']}{match_patterns['enc_bytes']}"
enc_match = re.search(pattern, line)
if enc_match:
enc = enc_match.group("enc_bytes")
return enc, asm_text
def gen_tests_in_dir(self, curr_dir: Path) -> list[str]:
"""Generate testcases from the files in the given dir.
Returns a list of files which failed to parse.
"""
fails = list()
for file in curr_dir.iterdir():
if file.is_dir():
self.gen_tests_in_dir(file)
continue
if len(self.included) != 0 and not any(
re.search(x, file.name) is not None for x in self.included
):
continue
if any(re.search(x, file.name) is not None for x in self.excluded):
continue
if test_file := self.parse_file(curr_dir.joinpath(file)):
self.test_files[file.name] = test_file
else:
fails.append(file.name)
return fails
def gen_all(self):
log.info("Generate MC regression tests")
assembly_tests = self.mc_dir.joinpath(f"{self.arch}")
disas_tests = self.mc_dir.joinpath(f"Disassembler/{self.arch}")
if not disas_tests.exists() or not disas_tests.is_dir():
raise ValueError(
f"'{disas_tests}' does not exits or is not a directory. Cannot generate tests from there."
)
if not assembly_tests.exists() or not assembly_tests.is_dir():
raise ValueError(
f"'{assembly_tests}' does not exits or is not a directory. Cannot generate tests from there."
)
fails = self.gen_tests_in_dir(disas_tests)
fails.extend(self.gen_tests_in_dir(assembly_tests))
sum_tests = sum([len(tf.tests) for tf in self.test_files.values()])
log.info(
f"Parse {len(self.test_files)} MC test files with a total of {sum_tests} tests."
self.test_files: list[TestFile] = list()
self.unified_test_cases = unified_test_cases
with open(get_path("{MCUPDATER_CONFIG_FILE}")) as f:
self.conf = json.loads(f.read())
# Additional mattr passed to llvm-mc
self.mattr: str = (
",".join(self.conf["additional_mattr"][self.arch])
if self.arch in self.conf["additional_mattr"]
else ""
)
if fails:
log.warning("The following files failed to parse:")
for f in fails:
log.warning(f"\t{f}")
self.write_to_build_dir()
# A list of options which are always added.
self.mandatory_options: str = (
self.conf["mandatory_options"][self.arch]
if self.arch in self.conf["mandatory_options"]
else list()
)
self.multi_mode = multi_mode
def check_prerequisites(self, paths):
for path in paths:
if not path.exists() or not path.is_dir():
raise ValueError(
f"'{path}' does not exits or is not a directory. Cannot generate tests from there."
)
llvm_lit_cfg = get_path("{LLVM_LIT_TEST_DIR}")
if not llvm_lit_cfg.exists():
raise ValueError(
f"Could not find '{llvm_lit_cfg}'. Check {{LLVM_LIT_TEST_DIR}} in path_vars.json."
)
def write_to_build_dir(self):
for filename, test in self.test_files.items():
file_cnt = 0
test_cnt = 0
overwritten = 0
files_written = set()
for test in sorted(self.test_files):
if not test.has_tests():
continue
with open(
get_path("{MCUPDATER_OUT_DIR}").joinpath(f"{filename}.cs"), "w+"
) as f:
f.write(test.get_cs_testfile_content())
log.debug(f"Write {filename}")
file_cnt += 1
test_cnt += test.num_test_cases()
if self.multi_mode:
rel_path = str(
test.get_multi_mode_filename().relative_to(
get_path("{LLVM_LIT_TEST_DIR}")
)
)
else:
rel_path = str(
test.get_simple_filename().relative_to(
get_path("{LLVM_LIT_TEST_DIR}")
)
)
filename = re.sub(rf"{self.test_dir_link_prefix}\d+", ".", rel_path)
filename = get_path("{MCUPDATER_OUT_DIR}").joinpath(f"{filename}.yaml")
if filename in files_written:
write_mode = "a"
else:
write_mode = "w+"
filename.parent.mkdir(parents=True, exist_ok=True)
if self.multi_mode and filename.exists():
raise ValueError(
f"The following file exists already: {filename}\n"
"This is not allowed in multi-mode."
)
else:
log.debug(f"Overwrite: {filename}")
overwritten += 1
with open(filename, write_mode) as f:
f.write(test.get_cs_testfile_content(only_test=(write_mode == "a")))
log.debug(f"Write {filename}")
files_written.add(filename)
log.info(
f"Processed {file_cnt} files with {test_cnt} test cases. Generated {len(files_written)} files"
)
if overwritten > 0:
log.warning(
f"Overwrote {overwritten} test files with the same name.\n"
f"These files contain instructions of several different cpu features.\n"
f"You have to use multi-mode to write them into distinct files.\n"
f"The current setting will only keep the last one written.\n"
f"See also: https://github.com/capstone-engine/capstone/issues/1992"
)
def build_test_files(self, mc_cmds: list[LLVM_MC_Command]) -> list[TestFile]:
log.info("Build TestFile objects")
test_files = list()
n_all = len(mc_cmds)
for i, mcc in enumerate(mc_cmds):
print(f"{i + 1}/{n_all} {mcc.file.name}", flush=True, end="\r")
test_files.append(
TestFile(
self.arch,
mcc.file,
mcc.get_opts_list() + self.mandatory_options,
mcc,
self.unified_test_cases,
)
)
return test_files
def run_llvm_lit(self, paths: list[Path]) -> list[LLVM_MC_Command]:
"""
Calls llvm-lit with the given paths to the tests.
It parses the llvm-lit commands to LLVM_MC_Commands.
"""
lit_cfg_dir = get_path("{LLVM_LIT_TEST_DIR}")
llvm_lit_cfg = str(lit_cfg_dir.absolute())
args = ["lit", "-v", "-a", llvm_lit_cfg]
for i, p in enumerate(paths):
slink = lit_cfg_dir.joinpath(f"{self.test_dir_link_prefix}{i}")
self.symbolic_links.append(slink)
log.debug(f"Create link: {slink} -> {p}")
try:
slink.symlink_to(p, target_is_directory=True)
except FileExistsError as e:
print("Failed: Link existed. Please delete it")
raise e
log.info(f"Run lit: {' '.join(args)}")
cmds = sp.run(args, capture_output=True)
if cmds.stderr:
raise ValueError(f"llvm-lit failed with {cmds.stderr}")
return self.extract_llvm_mc_cmds(cmds.stdout.decode("utf8"))
def extract_llvm_mc_cmds(self, cmds: str) -> list[LLVM_MC_Command]:
log.debug("Parsing llvm-mc commands")
# Get only the RUN lines which have a show-encoding set.
cmd_lines = cmds.splitlines()
log.debug(f"NO FILTER: {cmd_lines}")
matches = list(
filter(
lambda l: (
l
if re.search(r"^RUN.+(show-encoding|disassemble)[^|]+", l)
else None
),
cmd_lines,
)
)
log.debug(f"FILTER RUN: {' '.join(matches)}")
# Don't add tests which are allowed to fail
matches = list(
filter(lambda m: None if re.search(r"not\s+llvm-mc", m) else m, matches)
)
log.debug(f"FILTER not llvm-mc: {' '.join(matches)}")
# Skip object file tests
matches = list(
filter(lambda m: None if re.search(r"filetype=obj", m) else m, matches)
)
log.debug(f"FILTER filetype=obj-mc: {' '.join(matches)}")
# Skip any relocation related tests.
matches = filter(lambda m: None if re.search(r"reloc", m) else m, matches)
# Remove 'RUN: at ...' prefix
matches = map(lambda m: re.sub(r"^RUN: at line \d+: ", "", m), matches)
# Remove redirection
matches = map(lambda m: re.sub(r"\d>&\d", "", m), matches)
# Remove unused arguments
matches = map(lambda m: re.sub(r"-o\s?-", "", m), matches)
# Remove redirection of stderr to a file
matches = map(lambda m: re.sub(r"2>\s?\S+", "", m), matches)
# Remove piping to FileCheck
matches = map(lambda m: re.sub(r"\|\s*FileCheck\s+.+", "", m), matches)
# Remove input stream
matches = map(lambda m: re.sub(r"\s+<", "", m), matches)
all_cmds = list()
for match in matches:
if self.included and not any(
re.search(x, match) is not None for x in self.included
):
continue
if any(re.search(x, match) is not None for x in self.excluded):
continue
llvm_mc_cmd = LLVM_MC_Command(match, self.mattr)
if not llvm_mc_cmd.cmd:
# Invalid
continue
all_cmds.append(llvm_mc_cmd)
log.debug(f"Added: {llvm_mc_cmd}")
log.debug(f"Extracted {len(all_cmds)} llvm-mc commands")
return all_cmds
def gen_all(self):
log.info("Check prerequisites")
disas_tests = self.mc_dir.joinpath(f"Disassembler/{self.arch}")
test_paths = [disas_tests]
self.check_prerequisites(test_paths)
log.info("Generate MC regression tests")
llvm_mc_cmds = self.run_llvm_lit(test_paths)
log.info(f"Got {len(llvm_mc_cmds)} llvm-mc commands to run")
self.test_files = self.build_test_files(llvm_mc_cmds)
for slink in self.symbolic_links:
log.debug(f"Unlink {slink}")
slink.unlink()
self.write_to_build_dir()
def parse_args() -> argparse.Namespace:
@ -399,7 +461,7 @@ def parse_args() -> argparse.Namespace:
"-a",
dest="arch",
help="Name of architecture to update.",
choices=["ARM", "PowerPC", "AArch64", "LoongArch"],
choices=TARGETS_LLVM_NAMING,
required=True,
)
parser.add_argument(
@ -416,6 +478,13 @@ def parse_args() -> argparse.Namespace:
nargs="+",
help="Specific list of file names to update (can be a regex pattern).",
)
parser.add_argument(
"-u",
dest="unified_tests",
action="store_true",
default=False,
help="If set, all instructions of a text segment will decoded and tested at once. Should be set, if instructions depend on each other.",
)
parser.add_argument(
"-v",
dest="verbosity",
@ -437,5 +506,9 @@ if __name__ == "__main__":
)
MCUpdater(
args.arch, args.mc_dir, args.excluded_files, args.included_files
args.arch,
args.mc_dir,
args.excluded_files,
args.included_files,
args.unified_tests,
).gen_all()

View File

@ -71,6 +71,13 @@ class PathVarHandler(metaclass=Singleton):
log.fatal(f"\t{m}")
exit(1)
def test_only_overwrite_var(self, var_name: str, new_path: Path):
if var_name not in self.paths:
raise ValueError(f"PathVarHandler doesn't have a path for '{var_name}'")
if not new_path.exists():
raise ValueError(f"New path doesn't exists: '{new_path}")
self.paths[var_name] = new_path
def get_path(self, name: str) -> Path:
if name not in self.paths:
raise ValueError(f"Path variable {name} has no path saved.")

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