mirror of
https://github.com/capstone-engine/capstone.git
synced 2024-11-26 23:10:32 +00:00
Modern Testing (#2456)
This commit is contained in:
parent
df72286749
commit
191db14531
78
.github/workflows/CITest.yml
vendored
78
.github/workflows/CITest.yml
vendored
@ -6,7 +6,7 @@ on:
|
|||||||
- "docs/**"
|
- "docs/**"
|
||||||
- "ChangeLog"
|
- "ChangeLog"
|
||||||
- "CREDITS.TXT"
|
- "CREDITS.TXT"
|
||||||
- "COMPILE.TXT"
|
- "COMPILE_MAKE.TXT"
|
||||||
- "COMPILE_MSVC.TXT"
|
- "COMPILE_MSVC.TXT"
|
||||||
- "COMPILE_CMAKE.TXT"
|
- "COMPILE_CMAKE.TXT"
|
||||||
- "HACK.TXT"
|
- "HACK.TXT"
|
||||||
@ -34,6 +34,7 @@ jobs:
|
|||||||
os: ubuntu-22.04,
|
os: ubuntu-22.04,
|
||||||
arch: x64,
|
arch: x64,
|
||||||
build-system: 'make',
|
build-system: 'make',
|
||||||
|
diet-build: 'OFF',
|
||||||
enable-asan: 'OFF'
|
enable-asan: 'OFF'
|
||||||
}
|
}
|
||||||
- {
|
- {
|
||||||
@ -41,34 +42,37 @@ jobs:
|
|||||||
os: ubuntu-22.04,
|
os: ubuntu-22.04,
|
||||||
arch: x64,
|
arch: x64,
|
||||||
build-system: 'cmake',
|
build-system: 'cmake',
|
||||||
|
diet-build: 'OFF',
|
||||||
enable-asan: 'OFF'
|
enable-asan: 'OFF'
|
||||||
}
|
}
|
||||||
- {
|
- {
|
||||||
name: 'ubuntu-22.04 x64 ASAN',
|
name: 'ubuntu-24.04 x64 ASAN',
|
||||||
os: ubuntu-latest,
|
os: ubuntu-24.04,
|
||||||
arch: x64,
|
arch: x64,
|
||||||
build-system: 'cmake',
|
build-system: 'cmake',
|
||||||
|
diet-build: 'OFF',
|
||||||
enable-asan: 'ON'
|
enable-asan: 'ON'
|
||||||
}
|
}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- 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: |
|
run: |
|
||||||
export LD_LIBRARY_PATH=`pwd`/tests/:$LD_LIBRARY_PATH
|
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
|
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
|
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
|
- name: make
|
||||||
if: startsWith(matrix.config.build-system, 'make')
|
if: startsWith(matrix.config.build-system, 'make')
|
||||||
run: |
|
run: |
|
||||||
./make.sh
|
./make.sh
|
||||||
make check
|
|
||||||
sudo make install
|
sudo make install
|
||||||
cp libcapstone.so.5 libcapstone.so.5.0
|
|
||||||
|
|
||||||
- name: cmake
|
- name: cmake
|
||||||
if: startsWith(matrix.config.build-system, 'cmake')
|
if: startsWith(matrix.config.build-system, 'cmake')
|
||||||
@ -82,47 +86,55 @@ jobs:
|
|||||||
# build shared library
|
# build shared library
|
||||||
cmake -DCAPSTONE_INSTALL=1 -DBUILD_SHARED_LIBS=1 -DCMAKE_INSTALL_PREFIX=/usr -DCAPSTONE_BUILD_CSTEST=ON -DENABLE_ASAN=${asan} ..
|
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
|
sudo cmake --build . --config Release --target install
|
||||||
cp libcapstone.* ../
|
|
||||||
cp libcapstone.* ../tests/
|
|
||||||
cp test_* ../tests/
|
|
||||||
|
|
||||||
- name: Lower number of KASL randomized address bits
|
- name: Lower number of KASL randomized address bits
|
||||||
run: |
|
run: |
|
||||||
# Work-around ASAN bug https://github.com/google/sanitizers/issues/1716
|
# Work-around ASAN bug https://github.com/google/sanitizers/issues/1716
|
||||||
sudo sysctl vm.mmap_rnd_bits=28
|
sudo sysctl vm.mmap_rnd_bits=28
|
||||||
|
|
||||||
- name: "Compatibility header test build"
|
- name: "Compatibility header test"
|
||||||
if: matrix.config.diet-build == 'OFF'
|
if: startsWith(matrix.config.build-system, 'cmake') && matrix.config.diet-build == 'OFF'
|
||||||
env:
|
|
||||||
asan: ${{ matrix.config.enable-asan }}
|
|
||||||
run: |
|
run: |
|
||||||
cd "$(git rev-parse --show-toplevel)/suite/auto-sync/c_tests/"
|
ctest --test-dir build --output-on-failure -R ASCompatibilityHeaderTest
|
||||||
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
|
|
||||||
|
|
||||||
- name: cstool - reaches disassembler engine
|
- name: cstool - reaches disassembler engine
|
||||||
run: |
|
run: |
|
||||||
sh suite/run_invalid_cstool.sh
|
sh suite/run_invalid_cstool.sh
|
||||||
|
|
||||||
- name: cstest (cmake)
|
- name: cstest unit tests
|
||||||
if: startsWith(matrix.config.build-system, 'cmake')
|
if: startsWith(matrix.config.build-system, 'cmake')
|
||||||
run: |
|
run: |
|
||||||
python suite/cstest/cstest_report.py -D -d suite/MC
|
ctest --test-dir build --output-on-failure -R UnitCSTest
|
||||||
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
|
|
||||||
|
|
||||||
- name: cstest (make)
|
- name: cstest integration tests
|
||||||
if: startsWith(matrix.config.build-system, 'make')
|
if: startsWith(matrix.config.build-system, 'cmake')
|
||||||
run: |
|
run: |
|
||||||
cd suite/cstest && ./build_cstest.sh
|
ctest --test-dir build --output-on-failure -R IntegrationCSTest
|
||||||
python cstest_report.py -D -t build/cstest -d ../MC
|
|
||||||
python cstest_report.py -D -t build/cstest -f issues.cs
|
- name: cstest MC
|
||||||
python cstest_report.py -D -t build/cstest -f ../../tests/cs_details/issue.cs
|
if: startsWith(matrix.config.build-system, 'cmake')
|
||||||
cd ../../
|
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:
|
Windows:
|
||||||
runs-on: ${{ matrix.config.os }}
|
runs-on: ${{ matrix.config.os }}
|
||||||
|
42
.github/workflows/auto-sync.yml
vendored
42
.github/workflows/auto-sync.yml
vendored
@ -3,11 +3,17 @@ on:
|
|||||||
push:
|
push:
|
||||||
paths:
|
paths:
|
||||||
- "suite/auto-sync/**"
|
- "suite/auto-sync/**"
|
||||||
|
- ".github/workflows/auto-sync.yml"
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
|
# Stop previous runs on the same branch on new push
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check:
|
check:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-24.04
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
working-directory: suite/auto-sync/
|
working-directory: suite/auto-sync/
|
||||||
@ -30,9 +36,22 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
python3.11 -m black --check src/autosync
|
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: |
|
run: |
|
||||||
git clone https://github.com/capstone-engine/llvm-capstone.git vendor/llvm_root
|
git clone https://github.com/capstone-engine/llvm-capstone.git vendor/llvm_root
|
||||||
|
|
||||||
|
- name: Build llvm-tblgen
|
||||||
|
run: |
|
||||||
cd vendor/llvm_root
|
cd vendor/llvm_root
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
@ -40,6 +59,17 @@ jobs:
|
|||||||
cmake --build . --target llvm-tblgen --config Debug
|
cmake --build . --target llvm-tblgen --config Debug
|
||||||
cd ../../../
|
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
|
- name: Test generation of inc files
|
||||||
run: |
|
run: |
|
||||||
./src/autosync/ASUpdater.py -d -a AArch64 -s IncGen
|
./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 PPC -s Translate
|
||||||
./src/autosync/ASUpdater.py --ci -d -a LoongArch -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
|
- name: Differ - Test save file is up-to-date
|
||||||
run: |
|
run: |
|
||||||
./src/autosync/cpptranslator/Differ.py -a AArch64 --check_saved
|
./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
|
||||||
|
13
.github/workflows/clang-tidy.yml
vendored
13
.github/workflows/clang-tidy.yml
vendored
@ -8,11 +8,11 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
analyze:
|
analyze:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-24.04
|
||||||
|
|
||||||
name: clang-tidy
|
name: clang-tidy
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Install clang-tidy
|
- name: Install clang-tidy
|
||||||
@ -26,9 +26,9 @@ jobs:
|
|||||||
CC=clang sudo cmake --build . --config Release
|
CC=clang sudo cmake --build . --config Release
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
- name: Install clang-tidy-15
|
- name: Install clang-tidy-18
|
||||||
run: |
|
run: |
|
||||||
sudo apt install clang-tidy-15
|
sudo apt install clang-tidy-18
|
||||||
|
|
||||||
- name: Check for warnings
|
- name: Check for warnings
|
||||||
env:
|
env:
|
||||||
@ -36,3 +36,8 @@ jobs:
|
|||||||
head_sha: ${{ github.event.pull_request.head.sha }}
|
head_sha: ${{ github.event.pull_request.head.sha }}
|
||||||
run: |
|
run: |
|
||||||
./run-clang-tidy.sh build
|
./run-clang-tidy.sh build
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
if: ${{ failure() }}
|
||||||
|
with:
|
||||||
|
path: ct-warnings.txt
|
||||||
|
27
.github/workflows/python-tests.yml
vendored
27
.github/workflows/python-tests.yml
vendored
@ -28,5 +28,30 @@ jobs:
|
|||||||
- name: Build and install capstone
|
- name: Build and install capstone
|
||||||
run: pip install ./bindings/python
|
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
|
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
5
.gitignore
vendored
@ -25,6 +25,7 @@
|
|||||||
# python
|
# python
|
||||||
bindings/python/build/
|
bindings/python/build/
|
||||||
bindings/python/capstone.egg-info/
|
bindings/python/capstone.egg-info/
|
||||||
|
bindings/python/cstest_py/src/cstest_py.egg**
|
||||||
bindings/cython/capstone.egg-info/
|
bindings/cython/capstone.egg-info/
|
||||||
*.pyc
|
*.pyc
|
||||||
|
|
||||||
@ -133,7 +134,6 @@ fuzz_disasm
|
|||||||
fuzz_decode_platform
|
fuzz_decode_platform
|
||||||
capstone_get_setup
|
capstone_get_setup
|
||||||
suite/fuzz/corpus
|
suite/fuzz/corpus
|
||||||
suite/cstest/cmocka/
|
|
||||||
|
|
||||||
*.s
|
*.s
|
||||||
|
|
||||||
@ -147,3 +147,6 @@ android-ndk-*
|
|||||||
|
|
||||||
# Auto-sync files
|
# Auto-sync files
|
||||||
suite/auto-sync/src/autosync.egg-info
|
suite/auto-sync/src/autosync.egg-info
|
||||||
|
|
||||||
|
# clangd cache
|
||||||
|
/.cache
|
||||||
|
@ -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_STATIC_RUNTIME "Embed static runtime" ${BUILD_SHARED_LIBS})
|
||||||
option(CAPSTONE_BUILD_MACOS_THIN "Disable universal2 builds on macOS" OFF)
|
option(CAPSTONE_BUILD_MACOS_THIN "Disable universal2 builds on macOS" OFF)
|
||||||
option(CAPSTONE_BUILD_DIET "Build diet library" 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_CSTOOL "Build cstool" ${PROJECT_IS_TOP_LEVEL})
|
||||||
option(CAPSTONE_BUILD_CSTEST "Build cstest" OFF)
|
option(CAPSTONE_BUILD_CSTEST "Build cstest" OFF)
|
||||||
option(CAPSTONE_USE_DEFAULT_ALLOC "Use default memory allocation functions" ON)
|
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_DEBUG "Whether to enable extra debug assertions" OFF)
|
||||||
option(CAPSTONE_INSTALL "Generate install target" ${PROJECT_IS_TOP_LEVEL})
|
option(CAPSTONE_INSTALL "Generate install target" ${PROJECT_IS_TOP_LEVEL})
|
||||||
option(ENABLE_ASAN "Enable address sanitizer" OFF)
|
option(ENABLE_ASAN "Enable address sanitizer" OFF)
|
||||||
|
option(ENABLE_COVERAGE "Enable test coverage" OFF)
|
||||||
|
|
||||||
if (ENABLE_ASAN)
|
if (ENABLE_ASAN)
|
||||||
|
message("Enabling ASAN")
|
||||||
add_definitions(-DASAN_ENABLED)
|
add_definitions(-DASAN_ENABLED)
|
||||||
add_compile_options(-fsanitize=address)
|
add_compile_options(-fsanitize=address)
|
||||||
add_link_options(-fsanitize=address)
|
add_link_options(-fsanitize=address)
|
||||||
endif()
|
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 building for OSX it's best to allow CMake to handle building both architectures
|
||||||
if(APPLE AND NOT CAPSTONE_BUILD_MACOS_THIN)
|
if(APPLE AND NOT CAPSTONE_BUILD_MACOS_THIN)
|
||||||
set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64")
|
set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64")
|
||||||
@ -208,8 +216,6 @@ set(HEADERS_COMMON
|
|||||||
include/capstone/loongarch.h
|
include/capstone/loongarch.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(TEST_SOURCES test_basic.c test_detail.c test_skipdata.c test_iter.c)
|
|
||||||
|
|
||||||
## architecture support
|
## architecture support
|
||||||
if(CAPSTONE_ARM_SUPPORT)
|
if(CAPSTONE_ARM_SUPPORT)
|
||||||
add_definitions(-DCAPSTONE_HAS_ARM)
|
add_definitions(-DCAPSTONE_HAS_ARM)
|
||||||
@ -239,7 +245,6 @@ if(CAPSTONE_ARM_SUPPORT)
|
|||||||
arch/ARM/ARMGenCSMappingInsnName.inc
|
arch/ARM/ARMGenCSMappingInsnName.inc
|
||||||
arch/ARM/ARMGenSystemRegister.inc
|
arch/ARM/ARMGenSystemRegister.inc
|
||||||
)
|
)
|
||||||
set(TEST_SOURCES ${TEST_SOURCES} test_arm.c)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CAPSTONE_AARCH64_SUPPORT)
|
if(CAPSTONE_AARCH64_SUPPORT)
|
||||||
@ -270,7 +275,6 @@ if(CAPSTONE_AARCH64_SUPPORT)
|
|||||||
arch/AArch64/AArch64GenCSMappingInsnName.inc
|
arch/AArch64/AArch64GenCSMappingInsnName.inc
|
||||||
arch/AArch64/AArch64GenCSMappingInsnOp.inc
|
arch/AArch64/AArch64GenCSMappingInsnOp.inc
|
||||||
)
|
)
|
||||||
set(TEST_SOURCES ${TEST_SOURCES} test_aarch64.c)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CAPSTONE_MIPS_SUPPORT)
|
if(CAPSTONE_MIPS_SUPPORT)
|
||||||
@ -302,7 +306,6 @@ if(CAPSTONE_MIPS_SUPPORT)
|
|||||||
arch/Mips/MipsInstPrinter.h
|
arch/Mips/MipsInstPrinter.h
|
||||||
arch/Mips/MipsMapping.h
|
arch/Mips/MipsMapping.h
|
||||||
)
|
)
|
||||||
set(TEST_SOURCES ${TEST_SOURCES} test_mips.c)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CAPSTONE_PPC_SUPPORT)
|
if(CAPSTONE_PPC_SUPPORT)
|
||||||
@ -332,7 +335,6 @@ if(CAPSTONE_PPC_SUPPORT)
|
|||||||
arch/PowerPC/PPCGenSubtargetInfo.inc
|
arch/PowerPC/PPCGenSubtargetInfo.inc
|
||||||
arch/PowerPC/PPCGenRegisterInfo.inc
|
arch/PowerPC/PPCGenRegisterInfo.inc
|
||||||
)
|
)
|
||||||
set(TEST_SOURCES ${TEST_SOURCES} test_ppc.c)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CAPSTONE_X86_SUPPORT)
|
if(CAPSTONE_X86_SUPPORT)
|
||||||
@ -386,7 +388,6 @@ if(CAPSTONE_X86_SUPPORT)
|
|||||||
if(NOT CAPSTONE_BUILD_DIET)
|
if(NOT CAPSTONE_BUILD_DIET)
|
||||||
set(SOURCES_X86 ${SOURCES_X86} arch/X86/X86ATTInstPrinter.c)
|
set(SOURCES_X86 ${SOURCES_X86} arch/X86/X86ATTInstPrinter.c)
|
||||||
endif()
|
endif()
|
||||||
set(TEST_SOURCES ${TEST_SOURCES} test_x86.c test_customized_mnem.c)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CAPSTONE_SPARC_SUPPORT)
|
if(CAPSTONE_SPARC_SUPPORT)
|
||||||
@ -409,7 +410,6 @@ if(CAPSTONE_SPARC_SUPPORT)
|
|||||||
arch/Sparc/SparcMapping.h
|
arch/Sparc/SparcMapping.h
|
||||||
arch/Sparc/SparcMappingInsn.inc
|
arch/Sparc/SparcMappingInsn.inc
|
||||||
)
|
)
|
||||||
set(TEST_SOURCES ${TEST_SOURCES} test_sparc.c)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CAPSTONE_SYSZ_SUPPORT)
|
if(CAPSTONE_SYSZ_SUPPORT)
|
||||||
@ -434,7 +434,6 @@ if(CAPSTONE_SYSZ_SUPPORT)
|
|||||||
arch/SystemZ/SystemZMappingInsn.inc
|
arch/SystemZ/SystemZMappingInsn.inc
|
||||||
arch/SystemZ/SystemZMCTargetDesc.h
|
arch/SystemZ/SystemZMCTargetDesc.h
|
||||||
)
|
)
|
||||||
set(TEST_SOURCES ${TEST_SOURCES} test_systemz.c)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CAPSTONE_XCORE_SUPPORT)
|
if(CAPSTONE_XCORE_SUPPORT)
|
||||||
@ -455,7 +454,6 @@ if(CAPSTONE_XCORE_SUPPORT)
|
|||||||
arch/XCore/XCoreMapping.h
|
arch/XCore/XCoreMapping.h
|
||||||
arch/XCore/XCoreMappingInsn.inc
|
arch/XCore/XCoreMappingInsn.inc
|
||||||
)
|
)
|
||||||
set(TEST_SOURCES ${TEST_SOURCES} test_xcore.c)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CAPSTONE_M68K_SUPPORT)
|
if(CAPSTONE_M68K_SUPPORT)
|
||||||
@ -468,7 +466,6 @@ if(CAPSTONE_M68K_SUPPORT)
|
|||||||
set(HEADERS_M68K
|
set(HEADERS_M68K
|
||||||
arch/M68K/M68KDisassembler.h
|
arch/M68K/M68KDisassembler.h
|
||||||
)
|
)
|
||||||
set(TEST_SOURCES ${TEST_SOURCES} test_m68k.c)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CAPSTONE_TMS320C64X_SUPPORT)
|
if(CAPSTONE_TMS320C64X_SUPPORT)
|
||||||
@ -488,7 +485,6 @@ if(CAPSTONE_TMS320C64X_SUPPORT)
|
|||||||
arch/TMS320C64x/TMS320C64xInstPrinter.h
|
arch/TMS320C64x/TMS320C64xInstPrinter.h
|
||||||
arch/TMS320C64x/TMS320C64xMapping.h
|
arch/TMS320C64x/TMS320C64xMapping.h
|
||||||
)
|
)
|
||||||
set(TEST_SOURCES ${TEST_SOURCES} test_tms320c64x.c)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CAPSTONE_M680X_SUPPORT)
|
if(CAPSTONE_M680X_SUPPORT)
|
||||||
@ -503,7 +499,6 @@ if(CAPSTONE_M680X_SUPPORT)
|
|||||||
arch/M680X/M680XDisassembler.h
|
arch/M680X/M680XDisassembler.h
|
||||||
arch/M680X/M680XDisassemblerInternals.h
|
arch/M680X/M680XDisassemblerInternals.h
|
||||||
)
|
)
|
||||||
set(TEST_SOURCES ${TEST_SOURCES} test_m680x.c)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CAPSTONE_EVM_SUPPORT)
|
if(CAPSTONE_EVM_SUPPORT)
|
||||||
@ -520,7 +515,6 @@ if(CAPSTONE_EVM_SUPPORT)
|
|||||||
arch/EVM/EVMMapping.h
|
arch/EVM/EVMMapping.h
|
||||||
arch/EVM/EVMMappingInsn.inc
|
arch/EVM/EVMMappingInsn.inc
|
||||||
)
|
)
|
||||||
set(TEST_SOURCES ${TEST_SOURCES} test_evm.c)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CAPSTONE_WASM_SUPPORT)
|
if(CAPSTONE_WASM_SUPPORT)
|
||||||
@ -536,7 +530,6 @@ if(CAPSTONE_WASM_SUPPORT)
|
|||||||
arch/WASM/WASMInstPrinter.h
|
arch/WASM/WASMInstPrinter.h
|
||||||
arch/WASM/WASMMapping.h
|
arch/WASM/WASMMapping.h
|
||||||
)
|
)
|
||||||
set(TEST_SOURCES ${TEST_SOURCES} test_wasm.c)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CAPSTONE_MOS65XX_SUPPORT)
|
if(CAPSTONE_MOS65XX_SUPPORT)
|
||||||
@ -547,7 +540,6 @@ if(CAPSTONE_MOS65XX_SUPPORT)
|
|||||||
set(HEADERS_SOURCES_MOS65XX
|
set(HEADERS_SOURCES_MOS65XX
|
||||||
arch/MOS65XX/MOS65XXDisassembler.h
|
arch/MOS65XX/MOS65XXDisassembler.h
|
||||||
)
|
)
|
||||||
set(TEST_SOURCES ${TEST_SOURCES} test_mos65xx.c)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CAPSTONE_BPF_SUPPORT)
|
if(CAPSTONE_BPF_SUPPORT)
|
||||||
@ -565,7 +557,6 @@ if(CAPSTONE_BPF_SUPPORT)
|
|||||||
arch/BPF/BPFMapping.h
|
arch/BPF/BPFMapping.h
|
||||||
arch/BPF/BPFModule.h
|
arch/BPF/BPFModule.h
|
||||||
)
|
)
|
||||||
set(TEST_SOURCES ${TEST_SOURCES} test_bpf.c)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CAPSTONE_RISCV_SUPPORT)
|
if(CAPSTONE_RISCV_SUPPORT)
|
||||||
@ -591,7 +582,6 @@ if(CAPSTONE_RISCV_SUPPORT)
|
|||||||
arch/RISCV/RISCVMappingInsn.inc
|
arch/RISCV/RISCVMappingInsn.inc
|
||||||
arch/RISCV/RISCVMappingInsnOp.inc
|
arch/RISCV/RISCVMappingInsnOp.inc
|
||||||
)
|
)
|
||||||
set(TEST_SOURCES ${TEST_SOURCES} test_riscv.c)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CAPSTONE_SH_SUPPORT)
|
if(CAPSTONE_SH_SUPPORT)
|
||||||
@ -607,7 +597,6 @@ if(CAPSTONE_SH_SUPPORT)
|
|||||||
arch/SH/SHModule.h
|
arch/SH/SHModule.h
|
||||||
arch/SH/SHInsnTable.inc
|
arch/SH/SHInsnTable.inc
|
||||||
)
|
)
|
||||||
set(TEST_SOURCES ${TEST_SOURCES} test_sh.c)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CAPSTONE_TRICORE_SUPPORT)
|
if (CAPSTONE_TRICORE_SUPPORT)
|
||||||
@ -628,7 +617,6 @@ if (CAPSTONE_TRICORE_SUPPORT)
|
|||||||
arch/TriCore/TriCoreMapping.h
|
arch/TriCore/TriCoreMapping.h
|
||||||
arch/TriCore/TriCoreModule.h
|
arch/TriCore/TriCoreModule.h
|
||||||
)
|
)
|
||||||
set(TEST_SOURCES ${TEST_SOURCES} test_tricore.c)
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (CAPSTONE_ALPHA_SUPPORT)
|
if (CAPSTONE_ALPHA_SUPPORT)
|
||||||
@ -652,7 +640,6 @@ if (CAPSTONE_ALPHA_SUPPORT)
|
|||||||
arch/Alpha/AlphaGenCSMappingInsn.inc
|
arch/Alpha/AlphaGenCSMappingInsn.inc
|
||||||
arch/Alpha/AlphaGenCSMappingInsnName.inc
|
arch/Alpha/AlphaGenCSMappingInsnName.inc
|
||||||
)
|
)
|
||||||
set(TEST_SOURCES ${TEST_SOURCES} test_alpha.c)
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if(CAPSTONE_HPPA_SUPPORT)
|
if(CAPSTONE_HPPA_SUPPORT)
|
||||||
@ -670,7 +657,6 @@ if(CAPSTONE_HPPA_SUPPORT)
|
|||||||
arch/HPPA/HPPAMapping.h
|
arch/HPPA/HPPAMapping.h
|
||||||
arch/HPPA/HPPAModule.h
|
arch/HPPA/HPPAModule.h
|
||||||
)
|
)
|
||||||
set(TEST_SOURCES ${TEST_SOURCES} test_hppa.c)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CAPSTONE_LOONGARCH_SUPPORT)
|
if (CAPSTONE_LOONGARCH_SUPPORT)
|
||||||
@ -688,7 +674,6 @@ if (CAPSTONE_LOONGARCH_SUPPORT)
|
|||||||
arch/LoongArch/LoongArchModule.h
|
arch/LoongArch/LoongArchModule.h
|
||||||
arch/LoongArch/LoongArchLinkage.h
|
arch/LoongArch/LoongArchLinkage.h
|
||||||
)
|
)
|
||||||
set(TEST_SOURCES ${TEST_SOURCES} test_loongarch.c)
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (CAPSTONE_OSXKERNEL_SUPPORT)
|
if (CAPSTONE_OSXKERNEL_SUPPORT)
|
||||||
@ -766,27 +751,13 @@ if(BUILD_SHARED_LIBS)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CAPSTONE_BUILD_TESTS)
|
# Fuzzer if this is moved to it's own CMakeLists.txt (as it should be)
|
||||||
set(CMAKE_FOLDER "Tests")
|
# the OSS fuzzer build fails. And must be fixed.
|
||||||
enable_testing()
|
# Simply because it builds the fuzzer there again with hard-coded paths.
|
||||||
foreach(TSRC ${TEST_SOURCES})
|
# See: https://github.com/google/oss-fuzz/blob/master/projects/capstone/build.sh
|
||||||
string(REGEX REPLACE ".c$" "" TBIN ${TSRC})
|
# and: https://github.com/capstone-engine/capstone/issues/2454
|
||||||
add_executable(${TBIN} "tests/${TSRC}")
|
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(${TBIN} PRIVATE capstone)
|
target_link_libraries(fuzz_disasm 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()
|
|
||||||
|
|
||||||
source_group("Source\\Engine" FILES ${SOURCES_ENGINE})
|
source_group("Source\\Engine" FILES ${SOURCES_ENGINE})
|
||||||
source_group("Source\\ARM" FILES ${SOURCES_ARM})
|
source_group("Source\\ARM" FILES ${SOURCES_ARM})
|
||||||
@ -900,7 +871,6 @@ if(CAPSTONE_INSTALL)
|
|||||||
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||||
IMMEDIATE @ONLY
|
IMMEDIATE @ONLY
|
||||||
)
|
)
|
||||||
set(CMAKE_FOLDER)
|
|
||||||
add_custom_target(UNINSTALL COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
|
add_custom_target(UNINSTALL COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
|
||||||
set_target_properties(UNINSTALL PROPERTIES
|
set_target_properties(UNINSTALL PROPERTIES
|
||||||
FOLDER CMakePredefinedTargets
|
FOLDER CMakePredefinedTargets
|
||||||
@ -919,32 +889,17 @@ if(CAPSTONE_BUILD_CSTOOL)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CAPSTONE_BUILD_CSTEST)
|
if(CAPSTONE_BUILD_CSTEST)
|
||||||
include(ExternalProject)
|
enable_testing()
|
||||||
ExternalProject_Add(cmocka_ext
|
set(CSTEST_DIR ${PROJECT_SOURCE_DIR}/suite/cstest)
|
||||||
PREFIX extern
|
add_subdirectory(${CSTEST_DIR})
|
||||||
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)
|
|
||||||
|
|
||||||
file(GLOB CSTEST_SRC suite/cstest/src/*.c)
|
# Integration and unit tests
|
||||||
add_executable(cstest ${CSTEST_SRC})
|
set(TESTS_INTEGRATION_DIR ${PROJECT_SOURCE_DIR}/tests/integration)
|
||||||
add_dependencies(cstest cmocka_ext)
|
add_subdirectory(${TESTS_INTEGRATION_DIR})
|
||||||
target_link_libraries(cstest PUBLIC capstone cmocka)
|
set(TESTS_UNIT_DIR ${PROJECT_SOURCE_DIR}/tests/unit)
|
||||||
target_include_directories(cstest PRIVATE
|
add_subdirectory(${TESTS_UNIT_DIR})
|
||||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
|
||||||
${PROJECT_SOURCE_DIR}/suite/cstest/include
|
|
||||||
${CMOCKA_INCLUDE_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
if(CAPSTONE_INSTALL)
|
# Unit tests for auto-sync
|
||||||
install(TARGETS cstest EXPORT capstone-targets DESTINATION ${CMAKE_INSTALL_BINDIR})
|
set(AUTO_SYNC_C_TEST_DIR ${PROJECT_SOURCE_DIR}/suite/auto-sync/c_tests/)
|
||||||
endif()
|
add_subdirectory(${AUTO_SYNC_C_TEST_DIR})
|
||||||
endif()
|
endif()
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
This documentation explains how to compile Capstone with CMake, focus on
|
This documentation explains how to compile Capstone with CMake, focus on
|
||||||
using Microsoft Visual C as the compiler.
|
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.
|
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_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_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_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.
|
- ENABLE_ASAN: Compiles Capstone with the address sanitizer.
|
||||||
|
|
||||||
By default, Capstone use system dynamic memory management, and both DIET and X86_REDUCE
|
By default, Capstone use system dynamic memory management, and both DIET and X86_REDUCE
|
||||||
|
@ -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,
|
This documentation explains how to compile, install & run Capstone on MacOSX,
|
||||||
Linux, *BSD & Solaris. We also show steps to cross-compile for Microsoft Windows.
|
Linux, *BSD & Solaris. We also show steps to cross-compile for Microsoft Windows.
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
This documentation explains how to compile Capstone on Windows using
|
This documentation explains how to compile Capstone on Windows using
|
||||||
Microsoft Visual Studio version 2010 or newer.
|
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
|
To compile Capstone with CMake, see COMPILE_CMAKE.TXT
|
||||||
|
|
||||||
|
6
HACK.TXT
6
HACK.TXT
@ -3,7 +3,7 @@ Code structure
|
|||||||
|
|
||||||
Capstone source is organized as followings.
|
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
|
├── arch <- code handling disasm engine for each arch
|
||||||
│ ├── AArch64 <- AArch64 engine
|
│ ├── AArch64 <- AArch64 engine
|
||||||
│ ├── Alpha <- Alpha engine
|
│ ├── Alpha <- Alpha engine
|
||||||
@ -39,7 +39,7 @@ Capstone source is organized as followings.
|
|||||||
└── xcode <- Xcode support (for MacOSX compile)
|
└── 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
|
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:
|
the code and try to recompile/reinstall again. This can be done with:
|
||||||
@ -111,13 +111,13 @@ Compile:
|
|||||||
Tests:
|
Tests:
|
||||||
- tests/Makefile
|
- tests/Makefile
|
||||||
- tests/test_basic.c
|
- tests/test_basic.c
|
||||||
- tests/test_detail.c
|
|
||||||
- tests/test_iter.c
|
- tests/test_iter.c
|
||||||
- tests/test_newarch.c
|
- tests/test_newarch.c
|
||||||
- suite/fuzz/platform.c: add the architecture and its modes to the list of fuzzed platforms
|
- suite/fuzz/platform.c: add the architecture and its modes to the list of fuzzed platforms
|
||||||
- suite/capstone_get_setup.c
|
- suite/capstone_get_setup.c
|
||||||
- suite/MC/newarch/mode.mc: samples
|
- suite/MC/newarch/mode.mc: samples
|
||||||
- suite/test_corpus.py: correspondence between architecture and mode as text and architecture number for fuzzing
|
- suite/test_corpus.py: correspondence between architecture and mode as text and architecture number for fuzzing
|
||||||
|
- suite/cstest/
|
||||||
|
|
||||||
Bindings:
|
Bindings:
|
||||||
- bindings/Makefile
|
- bindings/Makefile
|
||||||
|
23
Makefile
23
Makefile
@ -457,12 +457,6 @@ PKGCFGF = $(BLDIR)/$(LIBNAME).pc
|
|||||||
all: $(LIBRARY) $(ARCHIVE) $(PKGCFGF)
|
all: $(LIBRARY) $(ARCHIVE) $(PKGCFGF)
|
||||||
ifeq (,$(findstring yes,$(CAPSTONE_BUILD_CORE_ONLY)))
|
ifeq (,$(findstring yes,$(CAPSTONE_BUILD_CORE_ONLY)))
|
||||||
@V=$(V) CC=$(CC) $(MAKE) -C cstool
|
@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
|
endif
|
||||||
|
|
||||||
ifeq ($(CAPSTONE_SHARED),yes)
|
ifeq ($(CAPSTONE_SHARED),yes)
|
||||||
@ -556,9 +550,7 @@ clean:
|
|||||||
|
|
||||||
ifeq (,$(findstring yes,$(CAPSTONE_BUILD_CORE_ONLY)))
|
ifeq (,$(findstring yes,$(CAPSTONE_BUILD_CORE_ONLY)))
|
||||||
$(MAKE) -C cstool clean
|
$(MAKE) -C cstool clean
|
||||||
$(MAKE) -C tests clean
|
|
||||||
$(MAKE) -C suite/fuzz clean
|
$(MAKE) -C suite/fuzz clean
|
||||||
rm -f $(BLDIR)/tests/lib$(LIBNAME).$(EXT)
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef BUILDDIR
|
ifdef BUILDDIR
|
||||||
@ -583,23 +575,8 @@ dist:
|
|||||||
git archive --format=tar.gz --prefix=capstone-$(DIST_VERSION)/ $(TAG) > capstone-$(DIST_VERSION).tgz
|
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
|
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
|
checkfuzz: fuzztest fuzzallcorp
|
||||||
|
|
||||||
test_%:
|
|
||||||
./tests/$@ > /dev/null && echo OK || echo FAILED
|
|
||||||
|
|
||||||
FUZZ_INPUTS = $(shell find suite/MC -type f -name '*.cs')
|
FUZZ_INPUTS = $(shell find suite/MC -type f -name '*.cs')
|
||||||
|
|
||||||
buildfuzz:
|
buildfuzz:
|
||||||
|
41
Mapping.c
41
Mapping.c
@ -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);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
23
Mapping.h
23
Mapping.h
@ -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);
|
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
|
#endif // CS_MAPPING_H
|
||||||
|
@ -49,7 +49,7 @@ Further information is available at https://www.capstone-engine.org
|
|||||||
Compile
|
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
|
Documentation
|
||||||
|
@ -35510,6 +35510,7 @@ static DecodeStatus fname(const uint8_t DecodeTable[], MCInst *MI, \
|
|||||||
/* Decoding complete. */ \
|
/* Decoding complete. */ \
|
||||||
return S; \
|
return S; \
|
||||||
} else { \
|
} else { \
|
||||||
|
MCInst_clear(MI); \
|
||||||
/* If the decoding was incomplete, skip. */ \
|
/* If the decoding was incomplete, skip. */ \
|
||||||
Ptr += NumToSkip; \
|
Ptr += NumToSkip; \
|
||||||
/* Reset decode status. This also drops a SoftFail status that could be */ \
|
/* Reset decode status. This also drops a SoftFail status that could be */ \
|
||||||
|
@ -462,12 +462,18 @@ void printInst(MCInst *MI, uint64_t Address, const char *Annot, SStream *O)
|
|||||||
if ((Opcode == AArch64_MOVZXi || Opcode == AArch64_MOVZWi ||
|
if ((Opcode == AArch64_MOVZXi || Opcode == AArch64_MOVZWi ||
|
||||||
Opcode == AArch64_MOVNXi || Opcode == AArch64_MOVNWi) &&
|
Opcode == AArch64_MOVNXi || Opcode == AArch64_MOVNWi) &&
|
||||||
MCOperand_isExpr(MCInst_getOperand(MI, (1)))) {
|
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) &&
|
if ((Opcode == AArch64_MOVKXi || Opcode == AArch64_MOVKWi) &&
|
||||||
MCOperand_isExpr(MCInst_getOperand(MI, (2)))) {
|
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
|
// 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));
|
printInt64Bang(O, MCOperand_getImm(Op));
|
||||||
SStream_concat0(O, markup(">"));
|
SStream_concat0(O, markup(">"));
|
||||||
} else {
|
} else {
|
||||||
SStream_concat0(O, "<llvm-expr>");
|
printUInt64Bang(O, MCInst_getOpVal(MI, OpNo));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1282,7 +1288,7 @@ DEFINE_printRegWithShiftExtend(false, 128, x, 0);
|
|||||||
assert(0 && \
|
assert(0 && \
|
||||||
"Unsupported predicate-as-counter register"); \
|
"Unsupported predicate-as-counter register"); \
|
||||||
SStream_concat(O, "%s", "pn"); \
|
SStream_concat(O, "%s", "pn"); \
|
||||||
printUInt32(O, (Reg - AArch64_P0)); \
|
printUInt32(O, (Reg - AArch64_PN0)); \
|
||||||
switch (EltSize) { \
|
switch (EltSize) { \
|
||||||
case 0: \
|
case 0: \
|
||||||
break; \
|
break; \
|
||||||
@ -1380,7 +1386,7 @@ void printUImm12Offset(MCInst *MI, unsigned OpNum, unsigned Scale, SStream *O)
|
|||||||
printUInt32Bang(O, (MCOperand_getImm(MO) * Scale));
|
printUInt32Bang(O, (MCOperand_getImm(MO) * Scale));
|
||||||
SStream_concat0(O, markup(">"));
|
SStream_concat0(O, markup(">"));
|
||||||
} else {
|
} 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);
|
printUInt32Bang(O, MCOperand_getImm(MO1) * Scale);
|
||||||
SStream_concat0(O, markup(">"));
|
SStream_concat0(O, markup(">"));
|
||||||
} else {
|
} else {
|
||||||
SStream_concat0(O, "<llvm-expr>");
|
printUInt64Bang(O, MCOperand_getImm(MO1));
|
||||||
}
|
}
|
||||||
SStream_concat0(O, "]");
|
SStream_concat0(O, "]");
|
||||||
}
|
}
|
||||||
@ -1964,7 +1970,7 @@ void printImplicitlyTypedVectorList(MCInst *MI, unsigned OpNum, SStream *O)
|
|||||||
NumLanes), \
|
NumLanes), \
|
||||||
LaneKind), \
|
LaneKind), \
|
||||||
OpNum, NumLanes, CHAR(LaneKind)); \
|
OpNum, NumLanes, CHAR(LaneKind)); \
|
||||||
if (CHAR(LaneKind) == 0) { \
|
if (CHAR(LaneKind) == '0') { \
|
||||||
printVectorList(MI, OpNum, O, ""); \
|
printVectorList(MI, OpNum, O, ""); \
|
||||||
return; \
|
return; \
|
||||||
} \
|
} \
|
||||||
@ -2026,7 +2032,7 @@ void printAlignedLabel(MCInst *MI, uint64_t Address, unsigned OpNum, SStream *O)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SStream_concat0(O, "<llvm-expr>");
|
printUInt64Bang(O, MCOperand_getImm(Op));
|
||||||
}
|
}
|
||||||
|
|
||||||
void printAdrLabel(MCInst *MI, uint64_t Address, unsigned OpNum, SStream *O)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SStream_concat0(O, "<llvm-expr>");
|
printUInt64Bang(O, MCOperand_getImm(Op));
|
||||||
}
|
}
|
||||||
|
|
||||||
void printAdrpLabel(MCInst *MI, uint64_t Address, unsigned OpNum, SStream *O)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SStream_concat0(O, "<llvm-expr>");
|
printUInt64Bang(O, MCOperand_getImm(Op));
|
||||||
}
|
}
|
||||||
|
|
||||||
void printAdrAdrpLabel(MCInst *MI, uint64_t Address, unsigned OpNum, SStream *O) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SStream_concat0(O, "<llvm-expr>");
|
printUInt64Bang(O, MCOperand_getImm(Op));
|
||||||
}
|
}
|
||||||
|
|
||||||
void printBarrierOption(MCInst *MI, unsigned OpNo, SStream *O)
|
void printBarrierOption(MCInst *MI, unsigned OpNo, SStream *O)
|
||||||
@ -2287,6 +2293,8 @@ void printSVEPattern(MCInst *MI, unsigned OpNum, SStream *O)
|
|||||||
AArch64SVEPredPattern_lookupSVEPREDPATByEncoding(Val);
|
AArch64SVEPredPattern_lookupSVEPREDPATByEncoding(Val);
|
||||||
if (Pat)
|
if (Pat)
|
||||||
SStream_concat0(O, Pat->Name);
|
SStream_concat0(O, Pat->Name);
|
||||||
|
else
|
||||||
|
printUInt32Bang(O, Val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void printSVEVecLenSpecifier(MCInst *MI, unsigned OpNum, SStream *O)
|
void printSVEVecLenSpecifier(MCInst *MI, unsigned OpNum, SStream *O)
|
||||||
@ -2371,7 +2379,7 @@ DECLARE_printImmSVE_U64(uint64_t);
|
|||||||
#define DEFINE_isSignedType(T) \
|
#define DEFINE_isSignedType(T) \
|
||||||
static inline bool CONCAT(isSignedType, T)() \
|
static inline bool CONCAT(isSignedType, T)() \
|
||||||
{ \
|
{ \
|
||||||
return CHAR(t) == 'i'; \
|
return CHAR(T) == 'i'; \
|
||||||
}
|
}
|
||||||
DEFINE_isSignedType(int8_t);
|
DEFINE_isSignedType(int8_t);
|
||||||
DEFINE_isSignedType(int16_t);
|
DEFINE_isSignedType(int16_t);
|
||||||
|
@ -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.type = AARCH64_SME_OP_INVALID;
|
||||||
AArch64_get_detail_op(MI, 0)->sme.tile = AARCH64_REG_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_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 = AARCH64_SLICE_IMM_INVALID;
|
||||||
AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm_range.first = -1;
|
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 = -1;
|
AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm_range.offset = AARCH64_SLICE_IMM_RANGE_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setup_pred_operand(MCInst *MI)
|
static void setup_pred_operand(MCInst *MI)
|
||||||
@ -556,6 +556,9 @@ static void AArch64_add_not_defined_ops(MCInst *MI, const SStream *OS)
|
|||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
case AARCH64_INS_ALIAS_FMOV:
|
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);
|
AArch64_insert_detail_op_float_at(MI, -1, 0.0f, CS_AC_READ);
|
||||||
break;
|
break;
|
||||||
case AARCH64_INS_ALIAS_LD1:
|
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);
|
int64_t Offset = MCInst_getOpVal(MI, OpNum);
|
||||||
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
|
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
|
||||||
(MI->address & -4) + Offset);
|
(MI->address & -4) + Offset);
|
||||||
|
} else {
|
||||||
|
// Expression
|
||||||
|
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
|
||||||
|
MCOperand_isImm(MCInst_getOperand(MI, OpNum)));
|
||||||
}
|
}
|
||||||
break;
|
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;
|
int64_t Offset = MCInst_getOpVal(MI, OpNum) * 4096;
|
||||||
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
|
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
|
||||||
(MI->address & -4096) + Offset);
|
(MI->address & -4096) + Offset);
|
||||||
|
} else {
|
||||||
|
// Expression
|
||||||
|
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
|
||||||
|
MCOperand_isImm(MCInst_getOperand(MI, OpNum)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AArch64_OP_GROUP_AdrAdrpLabel: {
|
case AArch64_OP_GROUP_AdrAdrpLabel: {
|
||||||
if (!MCOperand_isImm(MCInst_getOperand(MI, OpNum))) {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
int64_t Offset = MCInst_getOpVal(MI, OpNum);
|
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;
|
int64_t Offset = MCInst_getOpVal(MI, OpNum) * 4;
|
||||||
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
|
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
|
||||||
MI->address + Offset);
|
MI->address + Offset);
|
||||||
|
} else {
|
||||||
|
// Expression
|
||||||
|
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
|
||||||
|
MCOperand_isImm(MCInst_getOperand(MI, OpNum)));
|
||||||
}
|
}
|
||||||
break;
|
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_set_detail_op_sme(MI, OpNum,
|
||||||
AARCH64_SME_MATRIX_TILE_LIST,
|
AARCH64_SME_MATRIX_TILE_LIST,
|
||||||
AARCH64LAYOUT_VL_D,
|
AARCH64LAYOUT_VL_D,
|
||||||
AARCH64_REG_ZAD0 + I);
|
(int) (AARCH64_REG_ZAD0 + I));
|
||||||
AArch64_inc_op_count(MI);
|
AArch64_inc_op_count(MI);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1607,8 +1625,10 @@ static void add_cs_detail_general(MCInst *MI, aarch64_op_group op_group,
|
|||||||
unsigned Val = MCInst_getOpVal(MI, OpNum);
|
unsigned Val = MCInst_getOpVal(MI, OpNum);
|
||||||
const AArch64SVEPredPattern_SVEPREDPAT *Pat =
|
const AArch64SVEPredPattern_SVEPREDPAT *Pat =
|
||||||
AArch64SVEPredPattern_lookupSVEPREDPATByEncoding(Val);
|
AArch64SVEPredPattern_lookupSVEPREDPATByEncoding(Val);
|
||||||
if (!Pat)
|
if (!Pat) {
|
||||||
|
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM, Val);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
aarch64_sysop sysop;
|
aarch64_sysop sysop;
|
||||||
sysop.alias = Pat->SysAlias;
|
sysop.alias = Pat->SysAlias;
|
||||||
sysop.sub_type = AARCH64_OP_SVEPREDPAT;
|
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));
|
(1 << AArch64_AM_getShiftValue(Shift));
|
||||||
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
|
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
|
||||||
Val);
|
Val);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case AArch64_OP_GROUP_Imm8OptLsl_uint16_t:
|
case AArch64_OP_GROUP_Imm8OptLsl_uint16_t:
|
||||||
case AArch64_OP_GROUP_Imm8OptLsl_uint32_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));
|
(1 << AArch64_AM_getShiftValue(Shift));
|
||||||
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
|
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
|
||||||
Val);
|
Val);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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_set_detail_op_sme(MI, OpNum,
|
||||||
AARCH64_SME_MATRIX_SLICE_OFF,
|
AARCH64_SME_MATRIX_SLICE_OFF,
|
||||||
AARCH64LAYOUT_INVALID,
|
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) {
|
} else if (AArch64_get_detail_op(MI, 0)->type == AARCH64_OP_PRED) {
|
||||||
// The index is part of a predicate
|
// The index is part of a predicate
|
||||||
AArch64_set_detail_op_pred(MI, OpNum);
|
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;
|
unsigned EltSize = temp_arg_0;
|
||||||
AArch64_get_detail_op(MI, 0)->vas = EltSize;
|
AArch64_get_detail_op(MI, 0)->vas = EltSize;
|
||||||
AArch64_set_detail_op_reg(
|
AArch64_set_detail_op_reg(
|
||||||
MI, OpNum, MCInst_getOpVal(MI, OpNum) - AArch64_P0);
|
MI, OpNum, MCInst_getOpVal(MI, OpNum) - AArch64_PN0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AArch64_OP_GROUP_PrefetchOp_0:
|
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_2:
|
||||||
case AArch64_OP_GROUP_UImm12Offset_4:
|
case AArch64_OP_GROUP_UImm12Offset_4:
|
||||||
case AArch64_OP_GROUP_UImm12Offset_8: {
|
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,
|
AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
|
||||||
Scale * MCInst_getOpVal(MI, OpNum));
|
Scale * MCInst_getOpVal(MI, OpNum));
|
||||||
break;
|
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_h:
|
||||||
case AArch64_OP_GROUP_TypedVectorList_0_q:
|
case AArch64_OP_GROUP_TypedVectorList_0_q:
|
||||||
case AArch64_OP_GROUP_TypedVectorList_0_s:
|
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_16_b:
|
||||||
case AArch64_OP_GROUP_TypedVectorList_1_d:
|
case AArch64_OP_GROUP_TypedVectorList_1_d:
|
||||||
case AArch64_OP_GROUP_TypedVectorList_2_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':
|
case 'q':
|
||||||
vas = AARCH64LAYOUT_VL_Q;
|
vas = AARCH64LAYOUT_VL_Q;
|
||||||
break;
|
break;
|
||||||
case '\0':
|
case '0':
|
||||||
// Implicitly Typed register
|
// Implicitly Typed register
|
||||||
break;
|
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_h:
|
||||||
case AArch64_OP_GROUP_TypedVectorList_0_q:
|
case AArch64_OP_GROUP_TypedVectorList_0_q:
|
||||||
case AArch64_OP_GROUP_TypedVectorList_0_s:
|
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_16_b:
|
||||||
case AArch64_OP_GROUP_TypedVectorList_1_d:
|
case AArch64_OP_GROUP_TypedVectorList_1_d:
|
||||||
case AArch64_OP_GROUP_TypedVectorList_2_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) {
|
if (AArch64_get_detail_op(MI, 0)->type == AARCH64_OP_SME) {
|
||||||
AArch64_set_detail_op_sme(MI, OpNum,
|
AArch64_set_detail_op_sme(MI, OpNum,
|
||||||
AARCH64_SME_MATRIX_SLICE_OFF,
|
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) {
|
} else if (AArch64_get_detail_op(MI, 0)->type == AARCH64_OP_PRED) {
|
||||||
AArch64_set_detail_op_pred(MI, OpNum);
|
AArch64_set_detail_op_pred(MI, OpNum);
|
||||||
} else {
|
} 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,
|
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))
|
if (!detail_is_set(MI))
|
||||||
return;
|
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) {
|
if (AArch64_get_detail_op(MI, 0)->type == AARCH64_OP_SME) {
|
||||||
AArch64_set_detail_op_sme(MI, OpNum,
|
AArch64_set_detail_op_sme(MI, OpNum,
|
||||||
AARCH64_SME_MATRIX_SLICE_OFF_RANGE,
|
AARCH64_SME_MATRIX_SLICE_OFF_RANGE,
|
||||||
AARCH64LAYOUT_INVALID, FirstImm,
|
AARCH64LAYOUT_INVALID, (uint32_t) FirstImm,
|
||||||
Offset);
|
(uint32_t) Offset);
|
||||||
} else if (AArch64_get_detail_op(MI, 0)->type == AARCH64_OP_PRED) {
|
} else if (AArch64_get_detail_op(MI, 0)->type == AARCH64_OP_PRED) {
|
||||||
assert(0 && "Unkown SME predicate imm range type");
|
assert(0 && "Unkown SME predicate imm range type");
|
||||||
} else {
|
} else {
|
||||||
@ -2694,15 +2719,15 @@ void AArch64_set_detail_op_sme(MCInst *MI, unsigned OpNum,
|
|||||||
if (!detail_is_set(MI))
|
if (!detail_is_set(MI))
|
||||||
return;
|
return;
|
||||||
AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_SME;
|
AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_SME;
|
||||||
va_list args;
|
|
||||||
switch (part) {
|
switch (part) {
|
||||||
default:
|
default:
|
||||||
printf("Unhandled SME operand part %d\n", part);
|
printf("Unhandled SME operand part %d\n", part);
|
||||||
assert(0);
|
assert(0);
|
||||||
case AARCH64_SME_MATRIX_TILE_LIST:
|
case AARCH64_SME_MATRIX_TILE_LIST: {
|
||||||
setup_sme_operand(MI);
|
setup_sme_operand(MI);
|
||||||
|
va_list args;
|
||||||
va_start(args, vas);
|
va_start(args, vas);
|
||||||
int Tile = va_arg(args, int);
|
int Tile = va_arg(args, int); // NOLINT(clang-analyzer-valist.Uninitialized)
|
||||||
va_end(args);
|
va_end(args);
|
||||||
AArch64_get_detail_op(MI, 0)->sme.type = AARCH64_SME_OP_TILE;
|
AArch64_get_detail_op(MI, 0)->sme.type = AARCH64_SME_OP_TILE;
|
||||||
AArch64_get_detail_op(MI, 0)->sme.tile = 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_op(MI, 0)->access = map_get_op_access(MI, OpNum);
|
||||||
AArch64_get_detail(MI)->is_doing_sme = true;
|
AArch64_get_detail(MI)->is_doing_sme = true;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case AARCH64_SME_MATRIX_TILE:
|
case AARCH64_SME_MATRIX_TILE:
|
||||||
assert(map_get_op_type(MI, OpNum) == CS_OP_REG);
|
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 =
|
AArch64_get_detail_op(MI, 0)->sme.slice_reg =
|
||||||
MCInst_getOpVal(MI, OpNum);
|
MCInst_getOpVal(MI, OpNum);
|
||||||
break;
|
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);
|
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.
|
// 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 ==
|
assert(AArch64_get_detail_op(MI, 0)->type ==
|
||||||
AARCH64_OP_SME);
|
AARCH64_OP_SME);
|
||||||
assert(AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm ==
|
assert(AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm ==
|
||||||
-1);
|
AARCH64_SLICE_IMM_INVALID);
|
||||||
|
va_list args;
|
||||||
va_start(args, vas);
|
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);
|
va_end(args);
|
||||||
AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm =
|
AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm =
|
||||||
offset;
|
offset;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case AARCH64_SME_MATRIX_SLICE_OFF_RANGE: {
|
case AARCH64_SME_MATRIX_SLICE_OFF_RANGE: {
|
||||||
|
va_list args;
|
||||||
va_start(args, vas);
|
va_start(args, vas);
|
||||||
int8_t First = va_arg(args, int);
|
uint8_t First = va_arg(args, uint32_t); // NOLINT(clang-analyzer-valist.Uninitialized)
|
||||||
int8_t Offset = va_arg(args, int);
|
uint8_t Offset = va_arg(args, uint32_t); // NOLINT(clang-analyzer-valist.Uninitialized)
|
||||||
va_end(args);
|
va_end(args);
|
||||||
AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm_range.first =
|
AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm_range.first =
|
||||||
First;
|
First;
|
||||||
|
@ -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,
|
void AArch64_set_detail_op_imm(MCInst *MI, unsigned OpNum,
|
||||||
aarch64_op_type ImmType, int64_t Imm);
|
aarch64_op_type ImmType, int64_t Imm);
|
||||||
void AArch64_set_detail_op_imm_range(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);
|
||||||
void AArch64_set_detail_op_mem(MCInst *MI, unsigned OpNum, uint64_t Val);
|
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_op_mem_offset(MCInst *MI, unsigned OpNum, uint64_t Val);
|
||||||
void AArch64_set_detail_shift_ext(MCInst *MI, unsigned OpNum, bool SignExtend,
|
void AArch64_set_detail_shift_ext(MCInst *MI, unsigned OpNum, bool SignExtend,
|
||||||
|
@ -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)
|
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;
|
handle->syntax = (int)value;
|
||||||
|
} else if (type == CS_OPT_MODE) {
|
||||||
|
handle->mode = (cs_mode)value;
|
||||||
|
}
|
||||||
|
|
||||||
return CS_ERR_OK;
|
return CS_ERR_OK;
|
||||||
}
|
}
|
||||||
|
@ -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 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 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_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; }
|
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; }
|
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; }
|
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 */
|
/* Fake a split interface */
|
||||||
#define get_ea_mode_str_8(instruction) get_ea_mode_str(instruction, 0)
|
#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;
|
op->type = M68K_OP_IMM;
|
||||||
|
|
||||||
if (size == 1)
|
if (size == 1)
|
||||||
op->imm = read_imm_8(info) & 0xff;
|
op->imm = read_imm_8(info);
|
||||||
else if (size == 2)
|
else if (size == 2)
|
||||||
op->imm = read_imm_16(info) & 0xffff;
|
op->imm = read_imm_16(info);
|
||||||
else if (size == 4)
|
else if (size == 4)
|
||||||
op->imm = read_imm_32(info);
|
op->imm = read_imm_32(info);
|
||||||
else
|
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->type = M68K_OP_IMM;
|
||||||
op0->address_mode = M68K_AM_IMMEDIATE;
|
op0->address_mode = M68K_AM_IMMEDIATE;
|
||||||
op0->imm = imm;
|
op0->imm = imm & info->address_mask;
|
||||||
|
|
||||||
get_ea_mode_op(info, op1, info->ir, size);
|
get_ea_mode_op(info, op1, info->ir, size);
|
||||||
}
|
}
|
||||||
@ -878,7 +878,8 @@ static uint16_t reverse_bits(uint32_t v)
|
|||||||
s--;
|
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)
|
static uint8_t reverse_bits_8(uint32_t v)
|
||||||
@ -892,7 +893,8 @@ static uint8_t reverse_bits_8(uint32_t v)
|
|||||||
s--;
|
s--;
|
||||||
}
|
}
|
||||||
|
|
||||||
return r <<= s; // shift when v's highest bits are zero
|
r <<= s; // shift when v's highest bits are zero
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,17 +1,6 @@
|
|||||||
/* Capstone Disassembly Engine */
|
/* Capstone Disassembly Engine */
|
||||||
/* M68K Backend by Daniel Collin <daniel@collin.com> 2015-2016 */
|
/* 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 <stdio.h> // DEBUG
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -78,7 +67,7 @@ static const char* getRegName(m68k_reg reg)
|
|||||||
return s_reg_names[(int)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 first = 0;
|
||||||
unsigned int run_length = 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)
|
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)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printRegbitsRange(buffer, data & 0xff, "d");
|
printRegbitsRange(buffer, sizeof(buffer), data & 0xff, "d");
|
||||||
printRegbitsRange(buffer, (data >> 8) & 0xff, "a");
|
printRegbitsRange(buffer, sizeof(buffer), (data >> 8) & 0xff, "a");
|
||||||
printRegbitsRange(buffer, (data >> 16) & 0xff, "fp");
|
printRegbitsRange(buffer, sizeof(buffer), (data >> 16) & 0xff, "fp");
|
||||||
|
|
||||||
SStream_concat(O, "%s", buffer);
|
SStream_concat(O, "%s", buffer);
|
||||||
}
|
}
|
||||||
@ -386,3 +375,24 @@ const char *M68K_group_name(csh handle, unsigned int id)
|
|||||||
#endif
|
#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
|
||||||
|
|
||||||
|
@ -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_insn_name(csh handle, unsigned int id);
|
||||||
const char* M68K_group_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);
|
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
|
#endif
|
||||||
|
@ -13,7 +13,7 @@ cs_err M68K_global_init(cs_struct *ud)
|
|||||||
{
|
{
|
||||||
m68k_info *info;
|
m68k_info *info;
|
||||||
|
|
||||||
info = cs_mem_malloc(sizeof(m68k_info));
|
info = cs_mem_calloc(sizeof(m68k_info), 1);
|
||||||
if (!info) {
|
if (!info) {
|
||||||
return CS_ERR_MEM;
|
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_id = M68K_get_insn_id;
|
||||||
ud->insn_name = M68K_insn_name;
|
ud->insn_name = M68K_insn_name;
|
||||||
ud->group_name = M68K_group_name;
|
ud->group_name = M68K_group_name;
|
||||||
|
#ifndef CAPSTONE_DIET
|
||||||
|
ud->reg_access = M68K_reg_access;
|
||||||
|
#endif
|
||||||
|
|
||||||
return CS_ERR_OK;
|
return CS_ERR_OK;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
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;
|
handle->syntax = (int)value;
|
||||||
|
} else if (type == CS_OPT_MODE) {
|
||||||
|
handle->mode = (cs_mode)value;
|
||||||
|
}
|
||||||
|
|
||||||
return CS_ERR_OK;
|
return CS_ERR_OK;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
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;
|
handle->syntax = (int)value;
|
||||||
|
} else if (type == CS_OPT_MODE) {
|
||||||
|
handle->mode = (cs_mode)value;
|
||||||
|
}
|
||||||
|
|
||||||
return CS_ERR_OK;
|
return CS_ERR_OK;
|
||||||
}
|
}
|
||||||
|
@ -288,9 +288,7 @@ static void get_op_access(cs_struct *h, unsigned int id, uint8_t *access, uint64
|
|||||||
|
|
||||||
// initialize access
|
// initialize access
|
||||||
memset(access, 0, CS_X86_MAXIMUM_OPERAND_SIZE * sizeof(access[0]));
|
memset(access, 0, CS_X86_MAXIMUM_OPERAND_SIZE * sizeof(access[0]));
|
||||||
|
|
||||||
if (!arr) {
|
if (!arr) {
|
||||||
access[0] = 0;
|
|
||||||
return;
|
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
|
// copy in reverse order this access array from Intel syntax -> AT&T syntax
|
||||||
count--;
|
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)
|
if (arr[count - i] != CS_AC_IGNORE)
|
||||||
access[i] = arr[count - i];
|
access[i] = arr[count - i];
|
||||||
else
|
else
|
||||||
|
@ -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:
|
|
@ -1,11 +1,12 @@
|
|||||||
# Capstone Disassembler Engine
|
# Capstone Disassembler Engine
|
||||||
# By Dang Hoang Vu, 2013
|
# By Dang Hoang Vu, 2013
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import sys, re
|
import sys
|
||||||
|
import re
|
||||||
|
|
||||||
INCL_DIR = '../include/capstone/'
|
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 = {
|
template = {
|
||||||
'java': {
|
'java': {
|
||||||
@ -56,6 +57,7 @@ template = {
|
|||||||
'tricore.h': ['TRICORE', 'TriCore'],
|
'tricore.h': ['TRICORE', 'TriCore'],
|
||||||
'alpha.h': ['ALPHA', 'Alpha'],
|
'alpha.h': ['ALPHA', 'Alpha'],
|
||||||
'hppa.h': 'hppa',
|
'hppa.h': 'hppa',
|
||||||
|
'loongarch.h': 'loongarch',
|
||||||
'comment_open': '#',
|
'comment_open': '#',
|
||||||
'comment_close': '',
|
'comment_close': '',
|
||||||
},
|
},
|
||||||
@ -80,81 +82,6 @@ template = {
|
|||||||
'comment_open': '(*',
|
'comment_open': '(*',
|
||||||
'comment_close': ' *)',
|
'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 = {
|
excluded_prefixes = {
|
||||||
@ -237,6 +164,11 @@ def gen(lang):
|
|||||||
elif line.startswith('}') or line.startswith('#'):
|
elif line.startswith('}') or line.startswith('#'):
|
||||||
doc_lines = []
|
doc_lines = []
|
||||||
pass
|
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('//'):
|
if line == '' or line.startswith('//'):
|
||||||
continue
|
continue
|
||||||
@ -251,7 +183,7 @@ def gen(lang):
|
|||||||
xline.insert(1, '=') # insert an = so the expression below can parse it
|
xline.insert(1, '=') # insert an = so the expression below can parse it
|
||||||
line = ' '.join(xline)
|
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]):
|
if target in excluded_prefixes and any(x.startswith(excl_pre) for excl_pre in excluded_prefixes[target]):
|
||||||
return False
|
return False
|
||||||
if prefixs:
|
if prefixs:
|
||||||
@ -259,7 +191,7 @@ def gen(lang):
|
|||||||
else:
|
else:
|
||||||
return x.startswith(prefix.upper())
|
return x.startswith(prefix.upper())
|
||||||
|
|
||||||
if not is_with_prefix(line):
|
if not has_special_arch_prefix(line):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
tmp = line.strip().split(',')
|
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
|
t = re.sub(r'\((\d+)ULL << (\d+)\)', r'\1 << \2', t) # (1ULL<<1) to 1 << 1
|
||||||
f = re.split('\s+', t)
|
f = re.split('\s+', t)
|
||||||
|
|
||||||
if not is_with_prefix(f[0]):
|
if not has_special_arch_prefix(f[0]):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if len(f) > 1 and f[1] not in ('//', '///<', '='):
|
if len(f) > 1 and f[1] not in ('//', '///<', '='):
|
||||||
|
1
bindings/python/.gitignore
vendored
1
bindings/python/.gitignore
vendored
@ -1,6 +1,5 @@
|
|||||||
MANIFEST
|
MANIFEST
|
||||||
dist/
|
dist/
|
||||||
src/
|
|
||||||
capstone/lib
|
capstone/lib
|
||||||
capstone/include
|
capstone/include
|
||||||
pyx/lib
|
pyx/lib
|
||||||
|
@ -4,17 +4,12 @@
|
|||||||
|
|
||||||
1. To install Capstone and the Python bindings on *nix, run the command below:
|
1. To install Capstone and the Python bindings on *nix, run the command below:
|
||||||
|
|
||||||
$ sudo make install
|
```
|
||||||
|
pip install bindings/python/
|
||||||
To control the install destination, set the DESTDIR environment variable.
|
```
|
||||||
|
|
||||||
2. The tests directory contains some test code to show how to use the Capstone API.
|
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
|
- test_lite.py
|
||||||
Similarly to test_basic.py, but this code shows how to use disasm_lite(), a lighter
|
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
|
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
|
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
|
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().
|
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.
|
|
@ -40,6 +40,7 @@ __all__ = [
|
|||||||
'CS_ARCH_TRICORE',
|
'CS_ARCH_TRICORE',
|
||||||
'CS_ARCH_ALPHA',
|
'CS_ARCH_ALPHA',
|
||||||
'CS_ARCH_HPPA',
|
'CS_ARCH_HPPA',
|
||||||
|
'CS_ARCH_LOONGARCH',
|
||||||
'CS_ARCH_ALL',
|
'CS_ARCH_ALL',
|
||||||
|
|
||||||
'CS_MODE_LITTLE_ENDIAN',
|
'CS_MODE_LITTLE_ENDIAN',
|
||||||
@ -107,6 +108,8 @@ __all__ = [
|
|||||||
'CS_MODE_HPPA_11',
|
'CS_MODE_HPPA_11',
|
||||||
'CS_MODE_HPPA_20',
|
'CS_MODE_HPPA_20',
|
||||||
'CS_MODE_HPPA_20W',
|
'CS_MODE_HPPA_20W',
|
||||||
|
'CS_MODE_LOONGARCH32',
|
||||||
|
'CS_MODE_LOONGARCH64',
|
||||||
|
|
||||||
'CS_OPT_SYNTAX',
|
'CS_OPT_SYNTAX',
|
||||||
'CS_OPT_SYNTAX_DEFAULT',
|
'CS_OPT_SYNTAX_DEFAULT',
|
||||||
@ -225,6 +228,7 @@ CS_ARCH_SH = 16
|
|||||||
CS_ARCH_TRICORE = 17
|
CS_ARCH_TRICORE = 17
|
||||||
CS_ARCH_ALPHA = 18
|
CS_ARCH_ALPHA = 18
|
||||||
CS_ARCH_HPPA = 19
|
CS_ARCH_HPPA = 19
|
||||||
|
CS_ARCH_LOONGARCH = 20
|
||||||
CS_ARCH_MAX = 20
|
CS_ARCH_MAX = 20
|
||||||
CS_ARCH_ALL = 0xFFFF
|
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_11 = 1 << 1 # HPPA 1.1
|
||||||
CS_MODE_HPPA_20 = 1 << 2 # HPPA 2.0
|
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_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
|
# Capstone option type
|
||||||
CS_OPT_INVALID = 0 # No option specified
|
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_INVALID = 0 # Invalid/uninitialized access type.
|
||||||
CS_AC_READ = (1 << 0) # Operand that is read from.
|
CS_AC_READ = (1 << 0) # Operand that is read from.
|
||||||
CS_AC_WRITE = (1 << 1) # Operand that is written to.
|
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
|
# Capstone syntax value
|
||||||
CS_OPT_SYNTAX_DEFAULT = 1 << 1 # Default assembly syntax of all platforms (CS_OPT_SYNTAX)
|
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_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_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_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_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_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_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
|
# Capstone error type
|
||||||
CS_ERR_OK = 0 # No error: everything was fine
|
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]
|
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
|
# 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):
|
class _cs_arch(ctypes.Union):
|
||||||
_fields_ = (
|
_fields_ = (
|
||||||
@ -484,6 +492,7 @@ class _cs_arch(ctypes.Union):
|
|||||||
('tricore', tricore.CsTriCore),
|
('tricore', tricore.CsTriCore),
|
||||||
('alpha', alpha.CsAlpha),
|
('alpha', alpha.CsAlpha),
|
||||||
('hppa', hppa.CsHPPA),
|
('hppa', hppa.CsHPPA),
|
||||||
|
('loongarch', loongarch.CsLoongArch),
|
||||||
)
|
)
|
||||||
|
|
||||||
class _cs_detail(ctypes.Structure):
|
class _cs_detail(ctypes.Structure):
|
||||||
@ -695,6 +704,21 @@ class CsInsn(object):
|
|||||||
def size(self):
|
def size(self):
|
||||||
return self._raw.size
|
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).
|
# return instruction's machine bytes (which should have @size bytes).
|
||||||
@property
|
@property
|
||||||
def bytes(self):
|
def bytes(self):
|
||||||
@ -802,7 +826,7 @@ class CsInsn(object):
|
|||||||
elif arch == CS_ARCH_MIPS:
|
elif arch == CS_ARCH_MIPS:
|
||||||
self.operands = mips.get_arch_info(self._raw.detail.contents.arch.mips)
|
self.operands = mips.get_arch_info(self._raw.detail.contents.arch.mips)
|
||||||
elif arch == CS_ARCH_PPC:
|
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)
|
ppc.get_arch_info(self._raw.detail.contents.arch.ppc)
|
||||||
elif arch == CS_ARCH_SPARC:
|
elif arch == CS_ARCH_SPARC:
|
||||||
(self.cc, self.hint, self.operands) = sparc.get_arch_info(self._raw.detail.contents.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)
|
(self.operands) = alpha.get_arch_info(self._raw.detail.contents.arch.alpha)
|
||||||
elif arch == CS_ARCH_HPPA:
|
elif arch == CS_ARCH_HPPA:
|
||||||
(self.operands) = hppa.get_arch_info(self._raw.detail.contents.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):
|
def __getattr__(self, name):
|
||||||
@ -840,14 +866,14 @@ class CsInsn(object):
|
|||||||
|
|
||||||
attr = object.__getattribute__
|
attr = object.__getattribute__
|
||||||
if not attr(self, '_cs')._detail:
|
if not attr(self, '_cs')._detail:
|
||||||
raise AttributeError(name)
|
raise AttributeError(f"'CsInsn' has no attribute '{name}'")
|
||||||
_dict = attr(self, '__dict__')
|
_dict = attr(self, '__dict__')
|
||||||
if 'operands' not in _dict:
|
if 'operands' not in _dict:
|
||||||
self.__gen_detail()
|
self.__gen_detail()
|
||||||
if name not in _dict:
|
if name not in _dict:
|
||||||
if self._raw.id == 0:
|
if self._raw.id == 0:
|
||||||
raise CsError(CS_ERR_SKIPDATA)
|
raise CsError(CS_ERR_SKIPDATA)
|
||||||
raise AttributeError(name)
|
raise AttributeError(f"'CsInsn' has no attribute '{name}'")
|
||||||
return _dict[name]
|
return _dict[name]
|
||||||
|
|
||||||
# get the last error code
|
# get the last error code
|
||||||
@ -1021,9 +1047,16 @@ class Cs(object):
|
|||||||
except: # _cs might be pulled from under our feet
|
except: # _cs might be pulled from under our feet
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def option(self, opt_type, opt_value):
|
||||||
# def option(self, opt_type, opt_value):
|
status = _cs.cs_option(self.csh, opt_type, opt_value)
|
||||||
# return _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?
|
# is this a diet engine?
|
||||||
@ -1321,7 +1354,7 @@ def debug():
|
|||||||
"m680x": CS_ARCH_M680X, 'evm': CS_ARCH_EVM, 'mos65xx': CS_ARCH_MOS65XX,
|
"m680x": CS_ARCH_M680X, 'evm': CS_ARCH_EVM, 'mos65xx': CS_ARCH_MOS65XX,
|
||||||
'bpf': CS_ARCH_BPF, 'riscv': CS_ARCH_RISCV, 'tricore': CS_ARCH_TRICORE,
|
'bpf': CS_ARCH_BPF, 'riscv': CS_ARCH_RISCV, 'tricore': CS_ARCH_TRICORE,
|
||||||
'wasm': CS_ARCH_WASM, 'sh': CS_ARCH_SH, 'alpha': CS_ARCH_ALPHA,
|
'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 = ""
|
all_archs = ""
|
||||||
|
@ -14,7 +14,7 @@ class AArch64OpMem(ctypes.Structure):
|
|||||||
|
|
||||||
class AArch64ImmRange(ctypes.Structure):
|
class AArch64ImmRange(ctypes.Structure):
|
||||||
_fields_ = (
|
_fields_ = (
|
||||||
('imm', ctypes.c_int8),
|
('first', ctypes.c_int8),
|
||||||
('offset', ctypes.c_int8),
|
('offset', ctypes.c_int8),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -76,164 +76,166 @@ Alpha_REG_R31 = 64
|
|||||||
Alpha_REG_ENDING = 65
|
Alpha_REG_ENDING = 65
|
||||||
|
|
||||||
# Alpha instruction
|
# Alpha instruction
|
||||||
Alpha_INS_INVALID = 66
|
|
||||||
Alpha_INS_ADDL = 67
|
Alpha_INS_INVALID = 0
|
||||||
Alpha_INS_ADDQ = 68
|
Alpha_INS_ADDL = 1
|
||||||
Alpha_INS_ADDSsSU = 69
|
Alpha_INS_ADDQ = 2
|
||||||
Alpha_INS_ADDTsSU = 70
|
Alpha_INS_ADDSsSU = 3
|
||||||
Alpha_INS_AND = 71
|
Alpha_INS_ADDTsSU = 4
|
||||||
Alpha_INS_BEQ = 72
|
Alpha_INS_AND = 5
|
||||||
Alpha_INS_BGE = 73
|
Alpha_INS_BEQ = 6
|
||||||
Alpha_INS_BGT = 74
|
Alpha_INS_BGE = 7
|
||||||
Alpha_INS_BIC = 75
|
Alpha_INS_BGT = 8
|
||||||
Alpha_INS_BIS = 76
|
Alpha_INS_BIC = 9
|
||||||
Alpha_INS_BLBC = 77
|
Alpha_INS_BIS = 10
|
||||||
Alpha_INS_BLBS = 78
|
Alpha_INS_BLBC = 11
|
||||||
Alpha_INS_BLE = 79
|
Alpha_INS_BLBS = 12
|
||||||
Alpha_INS_BLT = 80
|
Alpha_INS_BLE = 13
|
||||||
Alpha_INS_BNE = 81
|
Alpha_INS_BLT = 14
|
||||||
Alpha_INS_BR = 82
|
Alpha_INS_BNE = 15
|
||||||
Alpha_INS_BSR = 83
|
Alpha_INS_BR = 16
|
||||||
Alpha_INS_CMOVEQ = 84
|
Alpha_INS_BSR = 17
|
||||||
Alpha_INS_CMOVGE = 85
|
Alpha_INS_CMOVEQ = 18
|
||||||
Alpha_INS_CMOVGT = 86
|
Alpha_INS_CMOVGE = 19
|
||||||
Alpha_INS_CMOVLBC = 87
|
Alpha_INS_CMOVGT = 20
|
||||||
Alpha_INS_CMOVLBS = 88
|
Alpha_INS_CMOVLBC = 21
|
||||||
Alpha_INS_CMOVLE = 89
|
Alpha_INS_CMOVLBS = 22
|
||||||
Alpha_INS_CMOVLT = 90
|
Alpha_INS_CMOVLE = 23
|
||||||
Alpha_INS_CMOVNE = 91
|
Alpha_INS_CMOVLT = 24
|
||||||
Alpha_INS_CMPBGE = 92
|
Alpha_INS_CMOVNE = 25
|
||||||
Alpha_INS_CMPEQ = 93
|
Alpha_INS_CMPBGE = 26
|
||||||
Alpha_INS_CMPLE = 94
|
Alpha_INS_CMPEQ = 27
|
||||||
Alpha_INS_CMPLT = 95
|
Alpha_INS_CMPLE = 28
|
||||||
Alpha_INS_CMPTEQsSU = 96
|
Alpha_INS_CMPLT = 29
|
||||||
Alpha_INS_CMPTLEsSU = 97
|
Alpha_INS_CMPTEQsSU = 30
|
||||||
Alpha_INS_CMPTLTsSU = 98
|
Alpha_INS_CMPTLEsSU = 31
|
||||||
Alpha_INS_CMPTUNsSU = 99
|
Alpha_INS_CMPTLTsSU = 32
|
||||||
Alpha_INS_CMPULE = 100
|
Alpha_INS_CMPTUNsSU = 33
|
||||||
Alpha_INS_CMPULT = 101
|
Alpha_INS_CMPULE = 34
|
||||||
Alpha_INS_COND_BRANCH = 102
|
Alpha_INS_CMPULT = 35
|
||||||
Alpha_INS_CPYSE = 103
|
Alpha_INS_COND_BRANCH = 36
|
||||||
Alpha_INS_CPYSN = 104
|
Alpha_INS_CPYSE = 37
|
||||||
Alpha_INS_CPYS = 105
|
Alpha_INS_CPYSN = 38
|
||||||
Alpha_INS_CTLZ = 106
|
Alpha_INS_CPYS = 39
|
||||||
Alpha_INS_CTPOP = 107
|
Alpha_INS_CTLZ = 40
|
||||||
Alpha_INS_CTTZ = 108
|
Alpha_INS_CTPOP = 41
|
||||||
Alpha_INS_CVTQSsSUI = 109
|
Alpha_INS_CTTZ = 42
|
||||||
Alpha_INS_CVTQTsSUI = 110
|
Alpha_INS_CVTQSsSUI = 43
|
||||||
Alpha_INS_CVTSTsS = 111
|
Alpha_INS_CVTQTsSUI = 44
|
||||||
Alpha_INS_CVTTQsSVC = 112
|
Alpha_INS_CVTSTsS = 45
|
||||||
Alpha_INS_CVTTSsSUI = 113
|
Alpha_INS_CVTTQsSVC = 46
|
||||||
Alpha_INS_DIVSsSU = 114
|
Alpha_INS_CVTTSsSUI = 47
|
||||||
Alpha_INS_DIVTsSU = 115
|
Alpha_INS_DIVSsSU = 48
|
||||||
Alpha_INS_ECB = 116
|
Alpha_INS_DIVTsSU = 49
|
||||||
Alpha_INS_EQV = 117
|
Alpha_INS_ECB = 50
|
||||||
Alpha_INS_EXCB = 118
|
Alpha_INS_EQV = 51
|
||||||
Alpha_INS_EXTBL = 119
|
Alpha_INS_EXCB = 52
|
||||||
Alpha_INS_EXTLH = 120
|
Alpha_INS_EXTBL = 53
|
||||||
Alpha_INS_EXTLL = 121
|
Alpha_INS_EXTLH = 54
|
||||||
Alpha_INS_EXTQH = 122
|
Alpha_INS_EXTLL = 55
|
||||||
Alpha_INS_EXTQL = 123
|
Alpha_INS_EXTQH = 56
|
||||||
Alpha_INS_EXTWH = 124
|
Alpha_INS_EXTQL = 57
|
||||||
Alpha_INS_EXTWL = 125
|
Alpha_INS_EXTWH = 58
|
||||||
Alpha_INS_FBEQ = 126
|
Alpha_INS_EXTWL = 59
|
||||||
Alpha_INS_FBGE = 127
|
Alpha_INS_FBEQ = 60
|
||||||
Alpha_INS_FBGT = 128
|
Alpha_INS_FBGE = 61
|
||||||
Alpha_INS_FBLE = 129
|
Alpha_INS_FBGT = 62
|
||||||
Alpha_INS_FBLT = 130
|
Alpha_INS_FBLE = 63
|
||||||
Alpha_INS_FBNE = 131
|
Alpha_INS_FBLT = 64
|
||||||
Alpha_INS_FCMOVEQ = 132
|
Alpha_INS_FBNE = 65
|
||||||
Alpha_INS_FCMOVGE = 133
|
Alpha_INS_FCMOVEQ = 66
|
||||||
Alpha_INS_FCMOVGT = 134
|
Alpha_INS_FCMOVGE = 67
|
||||||
Alpha_INS_FCMOVLE = 135
|
Alpha_INS_FCMOVGT = 68
|
||||||
Alpha_INS_FCMOVLT = 136
|
Alpha_INS_FCMOVLE = 69
|
||||||
Alpha_INS_FCMOVNE = 137
|
Alpha_INS_FCMOVLT = 70
|
||||||
Alpha_INS_FETCH = 138
|
Alpha_INS_FCMOVNE = 71
|
||||||
Alpha_INS_FETCH_M = 139
|
Alpha_INS_FETCH = 72
|
||||||
Alpha_INS_FTOIS = 140
|
Alpha_INS_FETCH_M = 73
|
||||||
Alpha_INS_FTOIT = 141
|
Alpha_INS_FTOIS = 74
|
||||||
Alpha_INS_INSBL = 142
|
Alpha_INS_FTOIT = 75
|
||||||
Alpha_INS_INSLH = 143
|
Alpha_INS_INSBL = 76
|
||||||
Alpha_INS_INSLL = 144
|
Alpha_INS_INSLH = 77
|
||||||
Alpha_INS_INSQH = 145
|
Alpha_INS_INSLL = 78
|
||||||
Alpha_INS_INSQL = 146
|
Alpha_INS_INSQH = 79
|
||||||
Alpha_INS_INSWH = 147
|
Alpha_INS_INSQL = 80
|
||||||
Alpha_INS_INSWL = 148
|
Alpha_INS_INSWH = 81
|
||||||
Alpha_INS_ITOFS = 149
|
Alpha_INS_INSWL = 82
|
||||||
Alpha_INS_ITOFT = 150
|
Alpha_INS_ITOFS = 83
|
||||||
Alpha_INS_JMP = 151
|
Alpha_INS_ITOFT = 84
|
||||||
Alpha_INS_JSR = 152
|
Alpha_INS_JMP = 85
|
||||||
Alpha_INS_JSR_COROUTINE = 153
|
Alpha_INS_JSR = 86
|
||||||
Alpha_INS_LDA = 154
|
Alpha_INS_JSR_COROUTINE = 87
|
||||||
Alpha_INS_LDAH = 155
|
Alpha_INS_LDA = 88
|
||||||
Alpha_INS_LDBU = 156
|
Alpha_INS_LDAH = 89
|
||||||
Alpha_INS_LDL = 157
|
Alpha_INS_LDBU = 90
|
||||||
Alpha_INS_LDL_L = 158
|
Alpha_INS_LDL = 91
|
||||||
Alpha_INS_LDQ = 159
|
Alpha_INS_LDL_L = 92
|
||||||
Alpha_INS_LDQ_L = 160
|
Alpha_INS_LDQ = 93
|
||||||
Alpha_INS_LDQ_U = 161
|
Alpha_INS_LDQ_L = 94
|
||||||
Alpha_INS_LDS = 162
|
Alpha_INS_LDQ_U = 95
|
||||||
Alpha_INS_LDT = 163
|
Alpha_INS_LDS = 96
|
||||||
Alpha_INS_LDWU = 164
|
Alpha_INS_LDT = 97
|
||||||
Alpha_INS_MB = 165
|
Alpha_INS_LDWU = 98
|
||||||
Alpha_INS_MSKBL = 166
|
Alpha_INS_MB = 99
|
||||||
Alpha_INS_MSKLH = 167
|
Alpha_INS_MSKBL = 100
|
||||||
Alpha_INS_MSKLL = 168
|
Alpha_INS_MSKLH = 101
|
||||||
Alpha_INS_MSKQH = 169
|
Alpha_INS_MSKLL = 102
|
||||||
Alpha_INS_MSKQL = 170
|
Alpha_INS_MSKQH = 103
|
||||||
Alpha_INS_MSKWH = 171
|
Alpha_INS_MSKQL = 104
|
||||||
Alpha_INS_MSKWL = 172
|
Alpha_INS_MSKWH = 105
|
||||||
Alpha_INS_MULL = 173
|
Alpha_INS_MSKWL = 106
|
||||||
Alpha_INS_MULQ = 174
|
Alpha_INS_MULL = 107
|
||||||
Alpha_INS_MULSsSU = 175
|
Alpha_INS_MULQ = 108
|
||||||
Alpha_INS_MULTsSU = 176
|
Alpha_INS_MULSsSU = 109
|
||||||
Alpha_INS_ORNOT = 177
|
Alpha_INS_MULTsSU = 110
|
||||||
Alpha_INS_RC = 178
|
Alpha_INS_ORNOT = 111
|
||||||
Alpha_INS_RET = 179
|
Alpha_INS_RC = 112
|
||||||
Alpha_INS_RPCC = 180
|
Alpha_INS_RET = 113
|
||||||
Alpha_INS_RS = 181
|
Alpha_INS_RPCC = 114
|
||||||
Alpha_INS_S4ADDL = 182
|
Alpha_INS_RS = 115
|
||||||
Alpha_INS_S4ADDQ = 183
|
Alpha_INS_S4ADDL = 116
|
||||||
Alpha_INS_S4SUBL = 184
|
Alpha_INS_S4ADDQ = 117
|
||||||
Alpha_INS_S4SUBQ = 185
|
Alpha_INS_S4SUBL = 118
|
||||||
Alpha_INS_S8ADDL = 186
|
Alpha_INS_S4SUBQ = 119
|
||||||
Alpha_INS_S8ADDQ = 187
|
Alpha_INS_S8ADDL = 120
|
||||||
Alpha_INS_S8SUBL = 188
|
Alpha_INS_S8ADDQ = 121
|
||||||
Alpha_INS_S8SUBQ = 189
|
Alpha_INS_S8SUBL = 122
|
||||||
Alpha_INS_SEXTB = 190
|
Alpha_INS_S8SUBQ = 123
|
||||||
Alpha_INS_SEXTW = 191
|
Alpha_INS_SEXTB = 124
|
||||||
Alpha_INS_SLL = 192
|
Alpha_INS_SEXTW = 125
|
||||||
Alpha_INS_SQRTSsSU = 193
|
Alpha_INS_SLL = 126
|
||||||
Alpha_INS_SQRTTsSU = 194
|
Alpha_INS_SQRTSsSU = 127
|
||||||
Alpha_INS_SRA = 195
|
Alpha_INS_SQRTTsSU = 128
|
||||||
Alpha_INS_SRL = 196
|
Alpha_INS_SRA = 129
|
||||||
Alpha_INS_STB = 197
|
Alpha_INS_SRL = 130
|
||||||
Alpha_INS_STL = 198
|
Alpha_INS_STB = 131
|
||||||
Alpha_INS_STL_C = 199
|
Alpha_INS_STL = 132
|
||||||
Alpha_INS_STQ = 200
|
Alpha_INS_STL_C = 133
|
||||||
Alpha_INS_STQ_C = 201
|
Alpha_INS_STQ = 134
|
||||||
Alpha_INS_STQ_U = 202
|
Alpha_INS_STQ_C = 135
|
||||||
Alpha_INS_STS = 203
|
Alpha_INS_STQ_U = 136
|
||||||
Alpha_INS_STT = 204
|
Alpha_INS_STS = 137
|
||||||
Alpha_INS_STW = 205
|
Alpha_INS_STT = 138
|
||||||
Alpha_INS_SUBL = 206
|
Alpha_INS_STW = 139
|
||||||
Alpha_INS_SUBQ = 207
|
Alpha_INS_SUBL = 140
|
||||||
Alpha_INS_SUBSsSU = 208
|
Alpha_INS_SUBQ = 141
|
||||||
Alpha_INS_SUBTsSU = 209
|
Alpha_INS_SUBSsSU = 142
|
||||||
Alpha_INS_TRAPB = 210
|
Alpha_INS_SUBTsSU = 143
|
||||||
Alpha_INS_UMULH = 211
|
Alpha_INS_TRAPB = 144
|
||||||
Alpha_INS_WH64 = 212
|
Alpha_INS_UMULH = 145
|
||||||
Alpha_INS_WH64EN = 213
|
Alpha_INS_WH64 = 146
|
||||||
Alpha_INS_WMB = 214
|
Alpha_INS_WH64EN = 147
|
||||||
Alpha_INS_XOR = 215
|
Alpha_INS_WMB = 148
|
||||||
Alpha_INS_ZAPNOT = 216
|
Alpha_INS_XOR = 149
|
||||||
ALPHA_INS_ENDING = 217
|
Alpha_INS_ZAPNOT = 150
|
||||||
|
ALPHA_INS_ENDING = 151
|
||||||
|
|
||||||
# Group of Alpha instructions
|
# Group of Alpha instructions
|
||||||
Alpha_GRP_INVALID = 218
|
|
||||||
|
Alpha_GRP_INVALID = 0
|
||||||
|
|
||||||
# Generic groups
|
# Generic groups
|
||||||
Alpha_GRP_CALL = 219
|
Alpha_GRP_CALL = 1
|
||||||
Alpha_GRP_JUMP = 220
|
Alpha_GRP_JUMP = 2
|
||||||
Alpha_GRP_BRANCH_RELATIVE = 221
|
Alpha_GRP_BRANCH_RELATIVE = 3
|
||||||
Alpha_GRP_ENDING = 222
|
Alpha_GRP_ENDING = 4
|
||||||
|
@ -12,6 +12,7 @@ class ArmOpMem(ctypes.Structure):
|
|||||||
('scale', ctypes.c_int),
|
('scale', ctypes.c_int),
|
||||||
('disp', ctypes.c_int),
|
('disp', ctypes.c_int),
|
||||||
('lshift', ctypes.c_int),
|
('lshift', ctypes.c_int),
|
||||||
|
('align', ctypes.c_uint),
|
||||||
)
|
)
|
||||||
|
|
||||||
class ArmOpShift(ctypes.Structure):
|
class ArmOpShift(ctypes.Structure):
|
||||||
@ -38,7 +39,7 @@ class ArmOpValue(ctypes.Union):
|
|||||||
_fields_ = (
|
_fields_ = (
|
||||||
('reg', ctypes.c_uint),
|
('reg', ctypes.c_uint),
|
||||||
('sysop', ArmOpSysop),
|
('sysop', ArmOpSysop),
|
||||||
('imm', ctypes.c_int32),
|
('imm', ctypes.c_int64),
|
||||||
('pred', ctypes.c_int),
|
('pred', ctypes.c_int),
|
||||||
('fp', ctypes.c_double),
|
('fp', ctypes.c_double),
|
||||||
('mem', ArmOpMem),
|
('mem', ArmOpMem),
|
||||||
|
File diff suppressed because it is too large
Load Diff
55
bindings/python/capstone/loongarch.py
Normal file
55
bindings/python/capstone/loongarch.py
Normal 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])
|
2401
bindings/python/capstone/loongarch_const.py
Normal file
2401
bindings/python/capstone/loongarch_const.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -60,5 +60,5 @@ class CsPpc(ctypes.Structure):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def get_arch_info(a):
|
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
@ -140,10 +140,11 @@ SH_OP_MEM_GBR_DISP = 6
|
|||||||
SH_OP_MEM_GBR_R0 = 7
|
SH_OP_MEM_GBR_R0 = 7
|
||||||
SH_OP_MEM_PCR = 8
|
SH_OP_MEM_PCR = 8
|
||||||
SH_OP_MEM_TBR_DISP = 9
|
SH_OP_MEM_TBR_DISP = 9
|
||||||
SH_INS_DSP_INVALID = 10
|
|
||||||
SH_INS_DSP_DOUBLE = 11
|
SH_INS_DSP_INVALID = 0
|
||||||
SH_INS_DSP_SINGLE = 12
|
SH_INS_DSP_DOUBLE = 1
|
||||||
SH_INS_DSP_PARALLEL = 13
|
SH_INS_DSP_SINGLE = 2
|
||||||
|
SH_INS_DSP_PARALLEL = 3
|
||||||
SH_INS_DSP_NOP = 1
|
SH_INS_DSP_NOP = 1
|
||||||
SH_INS_DSP_MOV = 2
|
SH_INS_DSP_MOV = 2
|
||||||
SH_INS_DSP_PSHL = 3
|
SH_INS_DSP_PSHL = 3
|
||||||
@ -174,177 +175,180 @@ SH_INS_DSP_PLDS = 27
|
|||||||
SH_INS_DSP_PSWAP = 28
|
SH_INS_DSP_PSWAP = 28
|
||||||
SH_INS_DSP_PWAD = 29
|
SH_INS_DSP_PWAD = 29
|
||||||
SH_INS_DSP_PWSB = 30
|
SH_INS_DSP_PWSB = 30
|
||||||
SH_OP_DSP_INVALID = 31
|
|
||||||
SH_OP_DSP_REG_PRE = 32
|
SH_OP_DSP_INVALID = 0
|
||||||
SH_OP_DSP_REG_IND = 33
|
SH_OP_DSP_REG_PRE = 1
|
||||||
SH_OP_DSP_REG_POST = 34
|
SH_OP_DSP_REG_IND = 2
|
||||||
SH_OP_DSP_REG_INDEX = 35
|
SH_OP_DSP_REG_POST = 3
|
||||||
SH_OP_DSP_REG = 36
|
SH_OP_DSP_REG_INDEX = 4
|
||||||
SH_OP_DSP_IMM = 37
|
SH_OP_DSP_REG = 5
|
||||||
SH_DSP_CC_INVALID = 38
|
SH_OP_DSP_IMM = 6
|
||||||
SH_DSP_CC_NONE = 39
|
|
||||||
SH_DSP_CC_DCT = 40
|
SH_DSP_CC_INVALID = 0
|
||||||
SH_DSP_CC_DCF = 41
|
SH_DSP_CC_NONE = 1
|
||||||
SH_INS_INVALID = 42
|
SH_DSP_CC_DCT = 2
|
||||||
SH_INS_ADD_r = 43
|
SH_DSP_CC_DCF = 3
|
||||||
SH_INS_ADD = 44
|
|
||||||
SH_INS_ADDC = 45
|
SH_INS_INVALID = 0
|
||||||
SH_INS_ADDV = 46
|
SH_INS_ADD_r = 1
|
||||||
SH_INS_AND = 47
|
SH_INS_ADD = 2
|
||||||
SH_INS_BAND = 48
|
SH_INS_ADDC = 3
|
||||||
SH_INS_BANDNOT = 49
|
SH_INS_ADDV = 4
|
||||||
SH_INS_BCLR = 50
|
SH_INS_AND = 5
|
||||||
SH_INS_BF = 51
|
SH_INS_BAND = 6
|
||||||
SH_INS_BF_S = 52
|
SH_INS_BANDNOT = 7
|
||||||
SH_INS_BLD = 53
|
SH_INS_BCLR = 8
|
||||||
SH_INS_BLDNOT = 54
|
SH_INS_BF = 9
|
||||||
SH_INS_BOR = 55
|
SH_INS_BF_S = 10
|
||||||
SH_INS_BORNOT = 56
|
SH_INS_BLD = 11
|
||||||
SH_INS_BRA = 57
|
SH_INS_BLDNOT = 12
|
||||||
SH_INS_BRAF = 58
|
SH_INS_BOR = 13
|
||||||
SH_INS_BSET = 59
|
SH_INS_BORNOT = 14
|
||||||
SH_INS_BSR = 60
|
SH_INS_BRA = 15
|
||||||
SH_INS_BSRF = 61
|
SH_INS_BRAF = 16
|
||||||
SH_INS_BST = 62
|
SH_INS_BSET = 17
|
||||||
SH_INS_BT = 63
|
SH_INS_BSR = 18
|
||||||
SH_INS_BT_S = 64
|
SH_INS_BSRF = 19
|
||||||
SH_INS_BXOR = 65
|
SH_INS_BST = 20
|
||||||
SH_INS_CLIPS = 66
|
SH_INS_BT = 21
|
||||||
SH_INS_CLIPU = 67
|
SH_INS_BT_S = 22
|
||||||
SH_INS_CLRDMXY = 68
|
SH_INS_BXOR = 23
|
||||||
SH_INS_CLRMAC = 69
|
SH_INS_CLIPS = 24
|
||||||
SH_INS_CLRS = 70
|
SH_INS_CLIPU = 25
|
||||||
SH_INS_CLRT = 71
|
SH_INS_CLRDMXY = 26
|
||||||
SH_INS_CMP_EQ = 72
|
SH_INS_CLRMAC = 27
|
||||||
SH_INS_CMP_GE = 73
|
SH_INS_CLRS = 28
|
||||||
SH_INS_CMP_GT = 74
|
SH_INS_CLRT = 29
|
||||||
SH_INS_CMP_HI = 75
|
SH_INS_CMP_EQ = 30
|
||||||
SH_INS_CMP_HS = 76
|
SH_INS_CMP_GE = 31
|
||||||
SH_INS_CMP_PL = 77
|
SH_INS_CMP_GT = 32
|
||||||
SH_INS_CMP_PZ = 78
|
SH_INS_CMP_HI = 33
|
||||||
SH_INS_CMP_STR = 79
|
SH_INS_CMP_HS = 34
|
||||||
SH_INS_DIV0S = 80
|
SH_INS_CMP_PL = 35
|
||||||
SH_INS_DIV0U = 81
|
SH_INS_CMP_PZ = 36
|
||||||
SH_INS_DIV1 = 82
|
SH_INS_CMP_STR = 37
|
||||||
SH_INS_DIVS = 83
|
SH_INS_DIV0S = 38
|
||||||
SH_INS_DIVU = 84
|
SH_INS_DIV0U = 39
|
||||||
SH_INS_DMULS_L = 85
|
SH_INS_DIV1 = 40
|
||||||
SH_INS_DMULU_L = 86
|
SH_INS_DIVS = 41
|
||||||
SH_INS_DT = 87
|
SH_INS_DIVU = 42
|
||||||
SH_INS_EXTS_B = 88
|
SH_INS_DMULS_L = 43
|
||||||
SH_INS_EXTS_W = 89
|
SH_INS_DMULU_L = 44
|
||||||
SH_INS_EXTU_B = 90
|
SH_INS_DT = 45
|
||||||
SH_INS_EXTU_W = 91
|
SH_INS_EXTS_B = 46
|
||||||
SH_INS_FABS = 92
|
SH_INS_EXTS_W = 47
|
||||||
SH_INS_FADD = 93
|
SH_INS_EXTU_B = 48
|
||||||
SH_INS_FCMP_EQ = 94
|
SH_INS_EXTU_W = 49
|
||||||
SH_INS_FCMP_GT = 95
|
SH_INS_FABS = 50
|
||||||
SH_INS_FCNVDS = 96
|
SH_INS_FADD = 51
|
||||||
SH_INS_FCNVSD = 97
|
SH_INS_FCMP_EQ = 52
|
||||||
SH_INS_FDIV = 98
|
SH_INS_FCMP_GT = 53
|
||||||
SH_INS_FIPR = 99
|
SH_INS_FCNVDS = 54
|
||||||
SH_INS_FLDI0 = 100
|
SH_INS_FCNVSD = 55
|
||||||
SH_INS_FLDI1 = 101
|
SH_INS_FDIV = 56
|
||||||
SH_INS_FLDS = 102
|
SH_INS_FIPR = 57
|
||||||
SH_INS_FLOAT = 103
|
SH_INS_FLDI0 = 58
|
||||||
SH_INS_FMAC = 104
|
SH_INS_FLDI1 = 59
|
||||||
SH_INS_FMOV = 105
|
SH_INS_FLDS = 60
|
||||||
SH_INS_FMUL = 106
|
SH_INS_FLOAT = 61
|
||||||
SH_INS_FNEG = 107
|
SH_INS_FMAC = 62
|
||||||
SH_INS_FPCHG = 108
|
SH_INS_FMOV = 63
|
||||||
SH_INS_FRCHG = 109
|
SH_INS_FMUL = 64
|
||||||
SH_INS_FSCA = 110
|
SH_INS_FNEG = 65
|
||||||
SH_INS_FSCHG = 111
|
SH_INS_FPCHG = 66
|
||||||
SH_INS_FSQRT = 112
|
SH_INS_FRCHG = 67
|
||||||
SH_INS_FSRRA = 113
|
SH_INS_FSCA = 68
|
||||||
SH_INS_FSTS = 114
|
SH_INS_FSCHG = 69
|
||||||
SH_INS_FSUB = 115
|
SH_INS_FSQRT = 70
|
||||||
SH_INS_FTRC = 116
|
SH_INS_FSRRA = 71
|
||||||
SH_INS_FTRV = 117
|
SH_INS_FSTS = 72
|
||||||
SH_INS_ICBI = 118
|
SH_INS_FSUB = 73
|
||||||
SH_INS_JMP = 119
|
SH_INS_FTRC = 74
|
||||||
SH_INS_JSR = 120
|
SH_INS_FTRV = 75
|
||||||
SH_INS_JSR_N = 121
|
SH_INS_ICBI = 76
|
||||||
SH_INS_LDBANK = 122
|
SH_INS_JMP = 77
|
||||||
SH_INS_LDC = 123
|
SH_INS_JSR = 78
|
||||||
SH_INS_LDRC = 124
|
SH_INS_JSR_N = 79
|
||||||
SH_INS_LDRE = 125
|
SH_INS_LDBANK = 80
|
||||||
SH_INS_LDRS = 126
|
SH_INS_LDC = 81
|
||||||
SH_INS_LDS = 127
|
SH_INS_LDRC = 82
|
||||||
SH_INS_LDTLB = 128
|
SH_INS_LDRE = 83
|
||||||
SH_INS_MAC_L = 129
|
SH_INS_LDRS = 84
|
||||||
SH_INS_MAC_W = 130
|
SH_INS_LDS = 85
|
||||||
SH_INS_MOV = 131
|
SH_INS_LDTLB = 86
|
||||||
SH_INS_MOVA = 132
|
SH_INS_MAC_L = 87
|
||||||
SH_INS_MOVCA = 133
|
SH_INS_MAC_W = 88
|
||||||
SH_INS_MOVCO = 134
|
SH_INS_MOV = 89
|
||||||
SH_INS_MOVI20 = 135
|
SH_INS_MOVA = 90
|
||||||
SH_INS_MOVI20S = 136
|
SH_INS_MOVCA = 91
|
||||||
SH_INS_MOVLI = 137
|
SH_INS_MOVCO = 92
|
||||||
SH_INS_MOVML = 138
|
SH_INS_MOVI20 = 93
|
||||||
SH_INS_MOVMU = 139
|
SH_INS_MOVI20S = 94
|
||||||
SH_INS_MOVRT = 140
|
SH_INS_MOVLI = 95
|
||||||
SH_INS_MOVT = 141
|
SH_INS_MOVML = 96
|
||||||
SH_INS_MOVU = 142
|
SH_INS_MOVMU = 97
|
||||||
SH_INS_MOVUA = 143
|
SH_INS_MOVRT = 98
|
||||||
SH_INS_MUL_L = 144
|
SH_INS_MOVT = 99
|
||||||
SH_INS_MULR = 145
|
SH_INS_MOVU = 100
|
||||||
SH_INS_MULS_W = 146
|
SH_INS_MOVUA = 101
|
||||||
SH_INS_MULU_W = 147
|
SH_INS_MUL_L = 102
|
||||||
SH_INS_NEG = 148
|
SH_INS_MULR = 103
|
||||||
SH_INS_NEGC = 149
|
SH_INS_MULS_W = 104
|
||||||
SH_INS_NOP = 150
|
SH_INS_MULU_W = 105
|
||||||
SH_INS_NOT = 151
|
SH_INS_NEG = 106
|
||||||
SH_INS_NOTT = 152
|
SH_INS_NEGC = 107
|
||||||
SH_INS_OCBI = 153
|
SH_INS_NOP = 108
|
||||||
SH_INS_OCBP = 154
|
SH_INS_NOT = 109
|
||||||
SH_INS_OCBWB = 155
|
SH_INS_NOTT = 110
|
||||||
SH_INS_OR = 156
|
SH_INS_OCBI = 111
|
||||||
SH_INS_PREF = 157
|
SH_INS_OCBP = 112
|
||||||
SH_INS_PREFI = 158
|
SH_INS_OCBWB = 113
|
||||||
SH_INS_RESBANK = 159
|
SH_INS_OR = 114
|
||||||
SH_INS_ROTCL = 160
|
SH_INS_PREF = 115
|
||||||
SH_INS_ROTCR = 161
|
SH_INS_PREFI = 116
|
||||||
SH_INS_ROTL = 162
|
SH_INS_RESBANK = 117
|
||||||
SH_INS_ROTR = 163
|
SH_INS_ROTCL = 118
|
||||||
SH_INS_RTE = 164
|
SH_INS_ROTCR = 119
|
||||||
SH_INS_RTS = 165
|
SH_INS_ROTL = 120
|
||||||
SH_INS_RTS_N = 166
|
SH_INS_ROTR = 121
|
||||||
SH_INS_RTV_N = 167
|
SH_INS_RTE = 122
|
||||||
SH_INS_SETDMX = 168
|
SH_INS_RTS = 123
|
||||||
SH_INS_SETDMY = 169
|
SH_INS_RTS_N = 124
|
||||||
SH_INS_SETRC = 170
|
SH_INS_RTV_N = 125
|
||||||
SH_INS_SETS = 171
|
SH_INS_SETDMX = 126
|
||||||
SH_INS_SETT = 172
|
SH_INS_SETDMY = 127
|
||||||
SH_INS_SHAD = 173
|
SH_INS_SETRC = 128
|
||||||
SH_INS_SHAL = 174
|
SH_INS_SETS = 129
|
||||||
SH_INS_SHAR = 175
|
SH_INS_SETT = 130
|
||||||
SH_INS_SHLD = 176
|
SH_INS_SHAD = 131
|
||||||
SH_INS_SHLL = 177
|
SH_INS_SHAL = 132
|
||||||
SH_INS_SHLL16 = 178
|
SH_INS_SHAR = 133
|
||||||
SH_INS_SHLL2 = 179
|
SH_INS_SHLD = 134
|
||||||
SH_INS_SHLL8 = 180
|
SH_INS_SHLL = 135
|
||||||
SH_INS_SHLR = 181
|
SH_INS_SHLL16 = 136
|
||||||
SH_INS_SHLR16 = 182
|
SH_INS_SHLL2 = 137
|
||||||
SH_INS_SHLR2 = 183
|
SH_INS_SHLL8 = 138
|
||||||
SH_INS_SHLR8 = 184
|
SH_INS_SHLR = 139
|
||||||
SH_INS_SLEEP = 185
|
SH_INS_SHLR16 = 140
|
||||||
SH_INS_STBANK = 186
|
SH_INS_SHLR2 = 141
|
||||||
SH_INS_STC = 187
|
SH_INS_SHLR8 = 142
|
||||||
SH_INS_STS = 188
|
SH_INS_SLEEP = 143
|
||||||
SH_INS_SUB = 189
|
SH_INS_STBANK = 144
|
||||||
SH_INS_SUBC = 190
|
SH_INS_STC = 145
|
||||||
SH_INS_SUBV = 191
|
SH_INS_STS = 146
|
||||||
SH_INS_SWAP_B = 192
|
SH_INS_SUB = 147
|
||||||
SH_INS_SWAP_W = 193
|
SH_INS_SUBC = 148
|
||||||
SH_INS_SYNCO = 194
|
SH_INS_SUBV = 149
|
||||||
SH_INS_TAS = 195
|
SH_INS_SWAP_B = 150
|
||||||
SH_INS_TRAPA = 196
|
SH_INS_SWAP_W = 151
|
||||||
SH_INS_TST = 197
|
SH_INS_SYNCO = 152
|
||||||
SH_INS_XOR = 198
|
SH_INS_TAS = 153
|
||||||
SH_INS_XTRCT = 199
|
SH_INS_TRAPA = 154
|
||||||
SH_INS_DSP = 200
|
SH_INS_TST = 155
|
||||||
SH_INS_ENDING = 201
|
SH_INS_XOR = 156
|
||||||
|
SH_INS_XTRCT = 157
|
||||||
|
SH_INS_DSP = 158
|
||||||
|
SH_INS_ENDING = 159
|
||||||
|
|
||||||
SH_GRP_INVALID = 0
|
SH_GRP_INVALID = 0
|
||||||
SH_GRP_JUMP = 1
|
SH_GRP_JUMP = 1
|
||||||
|
@ -39,6 +39,8 @@ SPARC_HINT_INVALID = 0
|
|||||||
SPARC_HINT_A = 1<<0
|
SPARC_HINT_A = 1<<0
|
||||||
SPARC_HINT_PT = 1<<1
|
SPARC_HINT_PT = 1<<1
|
||||||
SPARC_HINT_PN = 1<<2
|
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_INVALID = 0
|
||||||
SPARC_OP_REG = 1
|
SPARC_OP_REG = 1
|
||||||
|
@ -461,10 +461,11 @@ TRICORE_INS_XOR_LT = 388
|
|||||||
TRICORE_INS_XOR_NE = 389
|
TRICORE_INS_XOR_NE = 389
|
||||||
TRICORE_INS_XOR = 390
|
TRICORE_INS_XOR = 390
|
||||||
TRICORE_INS_ENDING = 391
|
TRICORE_INS_ENDING = 391
|
||||||
TRICORE_GRP_INVALID = 392
|
|
||||||
TRICORE_GRP_CALL = 393
|
TRICORE_GRP_INVALID = 0
|
||||||
TRICORE_GRP_JUMP = 394
|
TRICORE_GRP_CALL = 1
|
||||||
TRICORE_GRP_ENDING = 395
|
TRICORE_GRP_JUMP = 2
|
||||||
|
TRICORE_GRP_ENDING = 3
|
||||||
|
|
||||||
TRICORE_FEATURE_INVALID = 0
|
TRICORE_FEATURE_INVALID = 0
|
||||||
TRICORE_FEATURE_HasV110 = 128
|
TRICORE_FEATURE_HasV110 = 128
|
||||||
|
@ -398,6 +398,7 @@ X86_AVX_RM_RN = 1
|
|||||||
X86_AVX_RM_RD = 2
|
X86_AVX_RM_RD = 2
|
||||||
X86_AVX_RM_RU = 3
|
X86_AVX_RM_RU = 3
|
||||||
X86_AVX_RM_RZ = 4
|
X86_AVX_RM_RZ = 4
|
||||||
|
X86_PREFIX_0 = 0x0
|
||||||
X86_PREFIX_LOCK = 0xf0
|
X86_PREFIX_LOCK = 0xf0
|
||||||
X86_PREFIX_REP = 0xf3
|
X86_PREFIX_REP = 0xf3
|
||||||
X86_PREFIX_REPE = 0xf3
|
X86_PREFIX_REPE = 0xf3
|
||||||
|
4
bindings/python/cstest_py/README.md
Normal file
4
bindings/python/cstest_py/README.md
Normal 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.
|
18
bindings/python/cstest_py/pyproject.toml
Normal file
18
bindings/python/cstest_py/pyproject.toml
Normal 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"
|
337
bindings/python/cstest_py/src/cstest_py/compare.py
Normal file
337
bindings/python/cstest_py/src/cstest_py/compare.py
Normal 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
|
41
bindings/python/cstest_py/src/cstest_py/cs_modes.py
Normal file
41
bindings/python/cstest_py/src/cstest_py/cs_modes.py
Normal 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,
|
||||||
|
},
|
||||||
|
}
|
493
bindings/python/cstest_py/src/cstest_py/cstest.py
Executable file
493
bindings/python/cstest_py/src/cstest_py/cstest.py
Executable 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()
|
1511
bindings/python/cstest_py/src/cstest_py/details.py
Normal file
1511
bindings/python/cstest_py/src/cstest_py/details.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -72,10 +72,12 @@ else:
|
|||||||
LIBRARY_FILE = "libcapstone.so"
|
LIBRARY_FILE = "libcapstone.so"
|
||||||
STATIC_LIBRARY_FILE = 'libcapstone.a'
|
STATIC_LIBRARY_FILE = 'libcapstone.a'
|
||||||
|
|
||||||
|
|
||||||
def clean_bins():
|
def clean_bins():
|
||||||
shutil.rmtree(LIBS_DIR, ignore_errors=True)
|
shutil.rmtree(LIBS_DIR, ignore_errors=True)
|
||||||
shutil.rmtree(HEADERS_DIR, ignore_errors=True)
|
shutil.rmtree(HEADERS_DIR, ignore_errors=True)
|
||||||
|
|
||||||
|
|
||||||
def copy_sources():
|
def copy_sources():
|
||||||
"""Copy the C sources into the source directory.
|
"""Copy the C sources into the source directory.
|
||||||
This rearranges the source files under the python distribution
|
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"))
|
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, "*.[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, "LICENSES/*")))
|
||||||
src.extend(glob.glob(os.path.join(BUILD_DIR, "README")))
|
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, "*.TXT")))
|
||||||
src.extend(glob.glob(os.path.join(BUILD_DIR, "RELEASE_NOTES")))
|
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, "CMakeLists.txt")))
|
||||||
src.extend(glob.glob(os.path.join(BUILD_DIR, "pkgconfig.mk")))
|
|
||||||
|
|
||||||
for filename in src:
|
for filename in src:
|
||||||
outpath = os.path.join(SRC_DIR, os.path.basename(filename))
|
outpath = os.path.join(SRC_DIR, os.path.basename(filename))
|
||||||
logger.info("%s -> %s" % (filename, outpath))
|
logger.info("%s -> %s" % (filename, outpath))
|
||||||
shutil.copy(filename, outpath)
|
shutil.copy(filename, outpath)
|
||||||
|
|
||||||
|
|
||||||
def build_libraries():
|
def build_libraries():
|
||||||
"""
|
"""
|
||||||
Prepare the capstone directory for a binary distribution or installation.
|
Prepare the capstone directory for a binary distribution or installation.
|
||||||
@ -134,23 +133,22 @@ def build_libraries():
|
|||||||
|
|
||||||
os.chdir(BUILD_DIR)
|
os.chdir(BUILD_DIR)
|
||||||
|
|
||||||
# platform description refers at https://docs.python.org/3/library/sys.html#sys.platform
|
# Windows build: this process requires few things:
|
||||||
# Use cmake for both Darwin and Windows since it can generate fat binaries
|
# - MSVC installed
|
||||||
if SYSTEM == "win32" or SYSTEM == 'darwin':
|
# - Run this command in an environment setup for MSVC
|
||||||
# Windows build: this process requires few things:
|
if not os.path.exists("build_py"):
|
||||||
# - CMake + MSVC installed
|
os.mkdir("build_py")
|
||||||
# - Run this command in an environment setup for MSVC
|
os.chdir("build_py")
|
||||||
if not os.path.exists("build"): os.mkdir("build")
|
print("Build Directory: {}\n".format(os.getcwd()))
|
||||||
os.chdir("build")
|
# Only build capstone.dll / libcapstone.dylib
|
||||||
print("Build Directory: {}\n".format(os.getcwd()))
|
if SYSTEM == "win32":
|
||||||
# Only build capstone.dll / libcapstone.dylib
|
os.system('cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCAPSTONE_BUILD_LEGACY_TESTS=OFF -DCAPSTONE_BUILD_CSTOOL=OFF -G "NMake Makefiles" ..')
|
||||||
if SYSTEM == "win32":
|
elif 'AFL_NOOPT' in os.environ:
|
||||||
os.system('cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCAPSTONE_BUILD_TESTS=OFF -DCAPSTONE_BUILD_CSTOOL=OFF -G "NMake Makefiles" ..')
|
# build for test_corpus
|
||||||
else:
|
os.system('cmake -DBUILD_SHARED_LIBS=ON -DCAPSTONE_BUILD_LEGACY_TESTS=OFF -DCAPSTONE_BUILD_CSTOOL=OFF ..')
|
||||||
os.system('cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCAPSTONE_BUILD_TESTS=OFF -DCAPSTONE_BUILD_CSTOOL=OFF -G "Unix Makefiles" ..')
|
else:
|
||||||
os.system("cmake --build .")
|
os.system('cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCAPSTONE_BUILD_LEGACY_TESTS=OFF -DCAPSTONE_BUILD_CSTOOL=OFF -G "Unix Makefiles" ..')
|
||||||
else: # Unix incl. cygwin
|
os.system("cmake --build .")
|
||||||
os.system("CAPSTONE_BUILD_CORE_ONLY=yes bash ./make.sh")
|
|
||||||
|
|
||||||
shutil.copy(VERSIONED_LIBRARY_FILE, os.path.join(LIBS_DIR, LIBRARY_FILE))
|
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')
|
self.run_command('build')
|
||||||
return bdist_egg.run(self)
|
return bdist_egg.run(self)
|
||||||
|
|
||||||
def dummy_src():
|
|
||||||
return []
|
|
||||||
|
|
||||||
cmdclass = {}
|
cmdclass = {}
|
||||||
cmdclass['build'] = custom_build
|
cmdclass['build'] = custom_build
|
||||||
@ -192,6 +188,7 @@ cmdclass['bdist_egg'] = custom_bdist_egg
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
from setuptools.command.develop import develop
|
from setuptools.command.develop import develop
|
||||||
|
|
||||||
class custom_develop(develop):
|
class custom_develop(develop):
|
||||||
def run(self):
|
def run(self):
|
||||||
logger.info("Building C extensions")
|
logger.info("Building C extensions")
|
||||||
|
@ -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()
|
|
@ -1,26 +1,9 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import test_basic, test_arm, test_aarch64, test_detail, test_lite, test_m68k, test_mips, \
|
import test_lite
|
||||||
test_ppc, test_x86, test_skipdata, test_sparc, test_systemz, test_tms320c64x, test_customized_mnem, \
|
import test_skipdata
|
||||||
test_m680x, test_mos65xx, test_xcore, test_riscv, test_alpha, test_hppa
|
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_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_skipdata.test_class()
|
||||||
test_customized_mnem.test()
|
test_customized_mnem.test()
|
||||||
test_xcore.test_class()
|
|
||||||
test_riscv.test_class()
|
|
||||||
test_alpha.test_class()
|
|
||||||
test_hppa.test_class()
|
|
||||||
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -1,5 +1,5 @@
|
|||||||
# This file contains all customized compile options for Capstone.
|
# 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.
|
# Specify which archs you want to compile in. By default, we build all archs.
|
||||||
|
5
cs.c
5
cs.c
@ -1110,9 +1110,8 @@ cs_err CAPSTONE_API cs_option(csh ud, cs_opt_type type, size_t value)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CS_OPT_NO_BRANCH_OFFSET:
|
case CS_OPT_NO_BRANCH_OFFSET:
|
||||||
if (handle->PrintBranchImmNotAsAddress)
|
handle->PrintBranchImmNotAsAddress = value == CS_OPT_ON ? true : false;
|
||||||
return CS_ERR_OK;
|
return CS_ERR_OK;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!arch_configs[handle->arch].arch_option)
|
if (!arch_configs[handle->arch].arch_option)
|
||||||
|
@ -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));
|
printf("\t\toperands[%u].sme.tile: %s\n", i, cs_reg_name(handle, op->sme.tile));
|
||||||
if (op->sme.slice_reg != AARCH64_REG_INVALID)
|
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));
|
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);
|
printf("\t\toperands[%u].sme.slice_offset: ", i);
|
||||||
if (op->sme.has_range_offset)
|
if (op->sme.has_range_offset)
|
||||||
printf("%hhd:%hhd\n", op->sme.slice_offset.imm_range.first, op->sme.slice_offset.imm_range.offset);
|
printf("%hhd:%hhd\n", op->sme.slice_offset.imm_range.first, op->sme.slice_offset.imm_range.offset);
|
||||||
else
|
else
|
||||||
printf("%d\n", op->sme.slice_offset.imm);
|
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"));
|
printf("\t\toperands[%u].sme.is_vertical: %s\n", i, (op->sme.is_vertical ? "true" : "false"));
|
||||||
break;
|
break;
|
||||||
case AARCH64_OP_PRED:
|
case AARCH64_OP_PRED:
|
||||||
|
@ -1965,7 +1965,7 @@ typedef enum {
|
|||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
// generated content <AArch64GenCSSystemOperandsEnum.inc:GET_ENUM_VALUES_TSB> end
|
// generated content <AArch64GenCSSystemOperandsEnum.inc:GET_ENUM_VALUES_TSB> end
|
||||||
AArch64_TSB_ENDING,
|
AARCH64_TSB_ENDING,
|
||||||
} aarch64_tsb;
|
} aarch64_tsb;
|
||||||
|
|
||||||
typedef union {
|
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_TILE_VEC, ///< SME operand is a tile indexed by a register and/or immediate
|
||||||
} aarch64_sme_op_type;
|
} aarch64_sme_op_type;
|
||||||
|
|
||||||
|
#define AARCH64_SLICE_IMM_INVALID UINT16_MAX
|
||||||
|
#define AARCH64_SLICE_IMM_RANGE_INVALID UINT8_MAX
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int8_t first;
|
uint8_t first;
|
||||||
int8_t offset;
|
uint8_t offset;
|
||||||
} aarch64_imm_range;
|
} aarch64_imm_range;
|
||||||
|
|
||||||
/// SME Instruction's matrix operand
|
/// SME Instruction's matrix operand
|
||||||
@ -2799,9 +2802,9 @@ typedef struct {
|
|||||||
aarch64_reg tile; ///< Matrix tile register
|
aarch64_reg tile; ///< Matrix tile register
|
||||||
aarch64_reg slice_reg; ///< slice index reg
|
aarch64_reg slice_reg; ///< slice index reg
|
||||||
union {
|
union {
|
||||||
int8_t imm;
|
uint16_t imm; ///< Invalid if equal to AARCH64_SLICE_IMM_INVALID
|
||||||
aarch64_imm_range imm_range;
|
aarch64_imm_range imm_range; ///< Members are set to AARCH64_SLICE_IMM_RANGE_INVALID if invalid.
|
||||||
} slice_offset; ///< slice index offset. Is set to -1 if invalid.
|
} slice_offset; ///< slice index offset.
|
||||||
bool has_range_offset; ///< If true, the offset is a range.
|
bool has_range_offset; ///< If true, the offset is a range.
|
||||||
bool is_vertical; ///< Flag if slice is vertical or horizontal
|
bool is_vertical; ///< Flag if slice is vertical or horizontal
|
||||||
} aarch64_op_sme;
|
} aarch64_op_sme;
|
||||||
|
@ -299,4 +299,4 @@ typedef enum alpha_insn_group {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -903,7 +903,7 @@ typedef struct cs_arm {
|
|||||||
ARMVCC_VPTCodes vcc; ///< Vector conditional code for this instruction.
|
ARMVCC_VPTCodes vcc; ///< Vector conditional code for this instruction.
|
||||||
bool update_flags; ///< does this insn update flags?
|
bool update_flags; ///< does this insn update flags?
|
||||||
bool post_index; ///< only set if writeback is 'True', if 'False' pre-index, otherwise post.
|
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.
|
// Check ARM_PredBlockMask for encoding details.
|
||||||
uint8_t /* ARM_PredBlockMask */ pred_mask; ///< Used by IT/VPT block instructions.
|
uint8_t /* ARM_PredBlockMask */ pred_mask; ///< Used by IT/VPT block instructions.
|
||||||
/// Number of operands of this instruction,
|
/// Number of operands of this instruction,
|
||||||
|
@ -1863,7 +1863,7 @@ typedef enum {
|
|||||||
|
|
||||||
ARM64_TSB_CSYNC = AARCH64_TSB_CSYNC,
|
ARM64_TSB_CSYNC = AARCH64_TSB_CSYNC,
|
||||||
|
|
||||||
ARM64_TSB_ENDING = AArch64_TSB_ENDING,
|
ARM64_TSB_ENDING = AARCH64_TSB_ENDING,
|
||||||
} arm64_tsb;
|
} arm64_tsb;
|
||||||
|
|
||||||
typedef aarch64_sysop_reg arm64_sysop_reg;
|
typedef aarch64_sysop_reg arm64_sysop_reg;
|
||||||
|
@ -284,7 +284,7 @@ typedef enum cs_opt_type {
|
|||||||
CS_OPT_SKIPDATA_SETUP, ///< Setup user-defined function for SKIPDATA option
|
CS_OPT_SKIPDATA_SETUP, ///< Setup user-defined function for SKIPDATA option
|
||||||
CS_OPT_MNEMONIC, ///< Customize instruction mnemonic
|
CS_OPT_MNEMONIC, ///< Customize instruction mnemonic
|
||||||
CS_OPT_UNSIGNED, ///< print immediate operands in unsigned form
|
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;
|
} cs_opt_type;
|
||||||
|
|
||||||
/// Runtime option value (associated with option type above)
|
/// 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_DETAIL_REAL = 1 << 1, ///< If enabled, always sets the real instruction detail. Even if the instruction is an alias.
|
||||||
} cs_opt_value;
|
} 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.
|
/// Common instruction groups - to be consistent across all architectures.
|
||||||
typedef enum cs_group_type {
|
typedef enum cs_group_type {
|
||||||
CS_GRP_INVALID = 0, ///< uninitialized/invalid group.
|
CS_GRP_INVALID = 0, ///< uninitialized/invalid group.
|
||||||
|
@ -540,4 +540,4 @@ typedef enum hppa_insn_group {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -3280,6 +3280,8 @@ typedef enum ppc_insn_group {
|
|||||||
/// PPC instruction formats. To get details about them please
|
/// PPC instruction formats. To get details about them please
|
||||||
/// refer to `PPCInstrFormats.td` in LLVM.
|
/// refer to `PPCInstrFormats.td` in LLVM.
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
PPC_INSN_FORM_INVALID = 0,
|
||||||
|
|
||||||
// generated content <PPCGenCSInsnFormatsEnum.inc> begin
|
// generated content <PPCGenCSInsnFormatsEnum.inc> begin
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
|
||||||
|
@ -64,6 +64,8 @@ typedef enum sparc_hint {
|
|||||||
SPARC_HINT_A = 1 << 0, ///< annul delay slot instruction
|
SPARC_HINT_A = 1 << 0, ///< annul delay slot instruction
|
||||||
SPARC_HINT_PT = 1 << 1, ///< branch taken
|
SPARC_HINT_PT = 1 << 1, ///< branch taken
|
||||||
SPARC_HINT_PN = 1 << 2, ///< branch NOT 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;
|
} sparc_hint;
|
||||||
|
|
||||||
/// Operand type for instruction's operands
|
/// Operand type for instruction's operands
|
||||||
|
@ -246,6 +246,7 @@ typedef enum x86_avx_rm {
|
|||||||
|
|
||||||
/// Instruction prefixes - to be used in cs_x86.prefix[]
|
/// Instruction prefixes - to be used in cs_x86.prefix[]
|
||||||
typedef enum x86_prefix {
|
typedef enum x86_prefix {
|
||||||
|
X86_PREFIX_0 = 0x0,
|
||||||
X86_PREFIX_LOCK = 0xf0, ///< lock (cs_x86.prefix[0]
|
X86_PREFIX_LOCK = 0xf0, ///< lock (cs_x86.prefix[0]
|
||||||
X86_PREFIX_REP = 0xf3, ///< rep (cs_x86.prefix[0]
|
X86_PREFIX_REP = 0xf3, ///< rep (cs_x86.prefix[0]
|
||||||
X86_PREFIX_REPE = 0xf3, ///< repe/repz (cs_x86.prefix[0]
|
X86_PREFIX_REPE = 0xf3, ///< repe/repz (cs_x86.prefix[0]
|
||||||
|
@ -18,10 +18,12 @@ BUILD_PATH="$1"
|
|||||||
|
|
||||||
check_list="clang-analyzer-*,-clang-analyzer-cplusplus*,-clang-analyzer-optin.performance.Padding"
|
check_list="clang-analyzer-*,-clang-analyzer-cplusplus*,-clang-analyzer-optin.performance.Padding"
|
||||||
|
|
||||||
if $(hash clang-tidy-15); then
|
if $(hash clang-tidy-18); then
|
||||||
clang-tidy-15 $(find ./arch ./*.c -type f -iregex ".*\.[c]") -p "$BUILD_PATH" -checks="$check_list" > ct-warnings.txt
|
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
|
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
|
fi
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
|
@ -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
19
suite/MC/README.md
Normal 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
|
||||||
|
...
|
||||||
|
```
|
15
suite/README
15
suite/README
@ -2,20 +2,9 @@ This directory contains some tools used by developers of Capstone project.
|
|||||||
Average users should ignore all the contents here.
|
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
|
- benchmark.py
|
||||||
This script benchmarks Python binding by disassembling some random code.
|
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_all.sh
|
||||||
Compile Capstone for all platforms (*nix32, clang, cygwin, cross-compile) &
|
Compile Capstone for all platforms (*nix32, clang, cygwin, cross-compile) &
|
||||||
report the result as pass or fail.
|
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)
|
This simple script disassembles random code for all archs (or selected arch)
|
||||||
in order to find segfaults.
|
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
|
- x86odd.py
|
||||||
Test some tricky X86 instructions.
|
Test some tricky X86 instructions.
|
||||||
|
|
||||||
|
@ -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
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
7
suite/auto-sync/.gitignore
vendored
7
suite/auto-sync/.gitignore
vendored
@ -4,4 +4,9 @@ vendor/llvm_root
|
|||||||
src/auto-sync/config.json
|
src/auto-sync/config.json
|
||||||
src/autosync/cpptranslator/Tests/Differ/test_saved_patches.json
|
src/autosync/cpptranslator/Tests/Differ/test_saved_patches.json
|
||||||
src/autosync.egg-info
|
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
|
||||||
|
@ -15,7 +15,7 @@ Please refer to [intro.md](intro.md) for an introduction about this tool.
|
|||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
Setup Python environment and Tree-sitter
|
#### Setup Python environment and Tree-sitter
|
||||||
|
|
||||||
```
|
```
|
||||||
cd <root-dir-Capstone>
|
cd <root-dir-Capstone>
|
||||||
@ -26,13 +26,35 @@ python3 -m venv ./.venv
|
|||||||
source ./.venv/bin/activate
|
source ./.venv/bin/activate
|
||||||
```
|
```
|
||||||
|
|
||||||
Install Auto-Sync framework
|
#### Install Auto-Sync framework
|
||||||
|
|
||||||
```
|
```
|
||||||
cd suite/auto-sync/
|
cd suite/auto-sync/
|
||||||
pip install -e .
|
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
|
## Architecture
|
||||||
|
|
||||||
Please read [ARCHITECTURE.md](https://github.com/capstone-engine/capstone/blob/next/docs/ARCHITECTURE.md) to understand how Auto-Sync works.
|
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
|
./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
|
Run the updater
|
||||||
|
|
||||||
```
|
```
|
||||||
|
16
suite/auto-sync/c_tests/CMakeLists.txt
Normal file
16
suite/auto-sync/c_tests/CMakeLists.txt
Normal 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}
|
||||||
|
)
|
@ -12,7 +12,7 @@ int main(void)
|
|||||||
csh handle;
|
csh handle;
|
||||||
|
|
||||||
if (cs_open(CS_ARCH_ARM64, CS_MODE_BIG_ENDIAN, &handle) != CS_ERR_OK) {
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,21 +20,48 @@ int main(void)
|
|||||||
|
|
||||||
cs_insn *insn;
|
cs_insn *insn;
|
||||||
uint8_t bytes[] = "0x1a,0x48,0xa0,0xf8";
|
uint8_t bytes[] = "0x1a,0x48,0xa0,0xf8";
|
||||||
size_t count = cs_disasm(handle, bytes, sizeof(bytes), 0x1000, 1, &insn);
|
size_t count =
|
||||||
if (count > 0) {
|
cs_disasm(handle, bytes, sizeof(bytes), 0x1000, 1, &insn);
|
||||||
printf("0x%" PRIx64 ":\t%s\t\t%s\n", insn[0].address,
|
if (count != 1) {
|
||||||
insn[0].mnemonic, insn[0].op_str);
|
fprintf(stderr, "Failed to disassemble code.\n");
|
||||||
printf("A register = %s\n", cs_reg_name(handle, insn[0].detail->arm64.operands[0].reg));
|
goto err;
|
||||||
printf("An imm = 0x%" PRIx64 "\n", insn[0].detail->arm64.operands[1].imm);
|
}
|
||||||
|
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);
|
if (insn[0].address != 0x1000) {
|
||||||
} else {
|
fprintf(stderr, "Address wrong.\n");
|
||||||
printf("ERROR: Failed to disassemble given code!\n");
|
goto err;
|
||||||
cs_close(&handle);
|
}
|
||||||
return -1;
|
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);
|
cs_close(&handle);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
printf("ERROR: Failed to disassemble given code corrcetly!\n");
|
||||||
|
cs_free(insn, count);
|
||||||
|
cs_close(&handle);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
#!/usr/bin/bash
|
#!/usr/bin/bash
|
||||||
|
|
||||||
python3.11 -m black src/autosync
|
python3 -m black src/autosync
|
||||||
|
@ -7,15 +7,15 @@ name = "autosync"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"termcolor >= 2.3.0",
|
"termcolor >= 2.3.0",
|
||||||
"tree_sitter >= 0.21.3",
|
"tree_sitter == 0.22.3",
|
||||||
"tree-sitter-cpp >=0.22.0",
|
"tree-sitter-cpp >=0.22.0",
|
||||||
"black >= 24.3.0",
|
"black >= 24.3.0",
|
||||||
"usort >= 1.0.8",
|
"usort >= 1.0.8",
|
||||||
"setuptools >= 69.2.0",
|
"setuptools >= 69.2.0",
|
||||||
"ninja >= 1.11.1.1",
|
"ninja >= 1.11.1.1",
|
||||||
"cmake >= 3.28.3",
|
|
||||||
"reuse >= 3.0.1",
|
"reuse >= 3.0.1",
|
||||||
"clang-format >= 18.1.1",
|
"clang-format >= 18.1.1",
|
||||||
|
"lit >= 18.1.8",
|
||||||
]
|
]
|
||||||
requires-python = ">= 3.11"
|
requires-python = ">= 3.11"
|
||||||
|
|
||||||
|
@ -73,7 +73,11 @@ class ASUpdater:
|
|||||||
self.inc_list,
|
self.inc_list,
|
||||||
)
|
)
|
||||||
self.mc_updater = MCUpdater(
|
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:
|
def clean_build_dir(self) -> None:
|
||||||
@ -192,6 +196,7 @@ class ASUpdater:
|
|||||||
log.info(f"Copied {i} files")
|
log.info(f"Copied {i} files")
|
||||||
|
|
||||||
# MC tests
|
# MC tests
|
||||||
|
i = 0
|
||||||
mc_dir = get_path("{MC_DIR}").joinpath(self.arch)
|
mc_dir = get_path("{MC_DIR}").joinpath(self.arch)
|
||||||
log.info(f"Copy MC test files to {mc_dir}")
|
log.info(f"Copy MC test files to {mc_dir}")
|
||||||
for file in get_path("{MCUPDATER_OUT_DIR}").iterdir():
|
for file in get_path("{MCUPDATER_OUT_DIR}").iterdir():
|
||||||
|
@ -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.
|
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
|
A valid sequence is a path from node_n to node_{(n + |node_types|-1)} where
|
||||||
!\f$\forall i \in \{0, ..., |node\_types|-1\}: type(node_{(n + i)}) = node\_types_i\f$.
|
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
|
If a node sequence is found, this functions returns the text associated with the
|
||||||
last node in the sequence.
|
last node in the sequence.
|
||||||
@ -159,6 +159,11 @@ def get_path(config_path: str) -> Path:
|
|||||||
return PathVarHandler().complete_path(config_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:
|
def fail_exit(msg: str) -> None:
|
||||||
"""Logs a fatal message and exits with error code 1."""
|
"""Logs a fatal message and exits with error code 1."""
|
||||||
log.fatal(msg)
|
log.fatal(msg)
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user