diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml new file mode 100644 index 0000000000..6f5e8554bc --- /dev/null +++ b/.github/workflows/python-publish.yml @@ -0,0 +1,80 @@ +name: PyPI 📦 Distribution + +on: [push] + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [macos-latest, ubuntu-latest, windows-latest] + platform: [x32, x64] + steps: + - uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + + - name: Set up MSVC x86 + if: matrix.os == 'windows-latest' && matrix.platform == 'x32' + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x86 + + - name: Set up MSVC x64 + if: matrix.os == 'windows-latest' && matrix.platform == 'x64' + uses: ilammy/msvc-dev-cmd@v1 + + - name: Install dependencies + run: | + pip install setuptools wheel + + - name: Build distribution 📦 + shell: bash + run: | + if [ ${{ matrix.platform }} == 'x32' ] && [ ${{ matrix.os }} == 'windows-latest' ]; then + cd bindings/python && python setup.py build -p win32 bdist_wheel -p win32 + elif [ ${{ matrix.platform }} == 'x32' ] && [ ${{ matrix.os }} == 'ubuntu-latest' ]; then + docker run --rm -v `pwd`/:/work dockcross/manylinux1-x86 > ./dockcross + chmod +x ./dockcross + ./dockcross bindings/python/build_wheel.sh + elif [ ${{ matrix.platform }} == 'x64' ] && [ ${{ matrix.os }} == 'ubuntu-latest' ]; then + docker run --rm -v `pwd`/:/work dockcross/manylinux1-x64 > ./dockcross + chmod +x ./dockcross + ./dockcross bindings/python/build_wheel.sh + elif [ ${{ matrix.platform }} == 'x32' ] && [ ${{ matrix.os }} == 'macos-latest' ]; then + cd bindings/python && python setup.py sdist + else + cd bindings/python && python setup.py bdist_wheel + fi + + - uses: actions/upload-artifact@v2 + with: + path: ${{ github.workspace }}/bindings/python/dist/* + + publish: + needs: [build] + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags') + steps: + - uses: actions/download-artifact@v2 + with: + name: artifact + path: dist + + - name: Publish distribution 📦 to test PyPI + uses: pypa/gh-action-pypi-publish@master + with: + user: __token__ + password: ${{ secrets.testpypi_pass }} + repository_url: https://test.pypi.org/legacy/ + + - name: Publish distribution 📦 to PyPI + if: ${{ success() }} + uses: pypa/gh-action-pypi-publish@master + with: + user: __token__ + password: ${{ secrets.pypi_pass }} diff --git a/.gitignore b/.gitignore index 33126c9dd5..8ccbfeff2f 100644 --- a/.gitignore +++ b/.gitignore @@ -115,6 +115,13 @@ fuzz_bindisasm fuzz_disasm capstone_get_setup +suite/fuzz/fuzz_bindisasm2 +suite/fuzz/fuzz_decode_platform +tests/test_bpf +tests/test_mos65xx +tests/test_riscv +tests/test_wasm + *.s diff --git a/CMakeLists.txt b/CMakeLists.txt index 197b6ba805..1715fda667 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,7 @@ option(CAPSTONE_BUILD_TESTS "Build tests" ON) option(CAPSTONE_BUILD_CSTOOL "Build cstool" ON) option(CAPSTONE_USE_DEFAULT_ALLOC "Use default memory allocation functions" ON) option(CAPSTONE_ARCHITECTURE_DEFAULT "Whether architectures are enabled by default" ON) +option(CAPSTONE_INSTALL "Generate install target" ON) set(SUPPORTED_ARCHITECTURES ARM ARM64 M68K MIPS PPC SPARC SYSZ XCORE X86 TMS320C64X M680X EVM) set(SUPPORTED_ARCHITECTURE_LABELS ARM ARM64 M68K MIPS PowerPC Sparc SystemZ XCore x86 TMS320C64x M680x EVM) @@ -563,17 +564,19 @@ source_group("Include\\EVM" FILES ${HEADERS_EVM}) include("GNUInstallDirs") ## installation -install(FILES ${HEADERS_COMMON} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/capstone) +if (CAPSTONE_INSTALL) + install(FILES ${HEADERS_COMMON} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/capstone) +endif () configure_file(capstone.pc.in ${CMAKE_BINARY_DIR}/capstone.pc @ONLY) -if (CAPSTONE_BUILD_STATIC) +if (CAPSTONE_BUILD_STATIC AND CAPSTONE_INSTALL) install(TARGETS capstone-static RUNTIME DESTINATION bin LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif () -if (CAPSTONE_BUILD_SHARED) +if (CAPSTONE_BUILD_SHARED AND CAPSTONE_INSTALL) install(TARGETS capstone-shared RUNTIME DESTINATION bin LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} @@ -585,6 +588,8 @@ FILE(GLOB CSTOOL_SRC cstool/*.c) add_executable(cstool ${CSTOOL_SRC}) target_link_libraries(cstool ${default-target}) -install(TARGETS cstool DESTINATION bin) -install(FILES ${CMAKE_BINARY_DIR}/capstone.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) +if (CAPSTONE_INSTALL) + install(TARGETS cstool DESTINATION bin) + install(FILES ${CMAKE_BINARY_DIR}/capstone.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) +endif () endif () diff --git a/COMPILE_MSVC.TXT b/COMPILE_MSVC.TXT index 68e02c2ccf..a082449652 100644 --- a/COMPILE_MSVC.TXT +++ b/COMPILE_MSVC.TXT @@ -106,3 +106,17 @@ versions, and Windows Driver Kit 10 or newer versions are required. >sc delete test_winkernel >bcdedit /deletevalue testsigning + + + +(3) Installing and building capstone via vcpkg + + You can download and install capstone using the vcpkg(https://github.com/Microsoft/vcpkg) dependency manager: + + git clone https://github.com/Microsoft/vcpkg.git + cd vcpkg + ./bootstrap-vcpkg.sh + ./vcpkg integrate install + vcpkg install capstone + + The capstone port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please create an issue or pull request on the vcpkg repository(https://github.com/Microsoft/vcpkg). \ No newline at end of file diff --git a/CREDITS.TXT b/CREDITS.TXT index f2581f345a..d266471e18 100644 --- a/CREDITS.TXT +++ b/CREDITS.TXT @@ -77,3 +77,6 @@ Fotis Loukos: TMS320C64x architecture. Wolfgang Schwotzer: M680X architecture. Philippe Antoine: Integration with oss-fuzz and various fixes. Stephen Eckels (stevemk14ebr): x86 encoding features +Sebastian Macke: MOS65XX architecture +Do Minh Tuan: Regression testing tool (cstest) +Kevin Foo (chfl4gs): PyPI github actions workflow. diff --git a/ChangeLog b/ChangeLog index af3ebf8565..9336bc9af1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,76 @@ This file details the changelog of Capstone. +---------------------------- +Version 4.0.2: May 8th, 2020 + + +[ Core ] + +- Windows kernel-mode driver support +- Fix installation path on FreeBSD and DragonFly + + +[ cstool ] + +- Add armv8, ppc32 & thumbv8 modes +- Print instruction ID + + +[ X86 ] + +- Support CS_OPT_UNSIGNED for ATT syntax +- Fix operand size for some instructions +- Fix LOCK prefixes +- Recognize xacquire/xrelease prefix +- Fix call/jmp access mode of mem operand +- Add ENDBR32, ENDBR64 to reduce mode +- Other minor fixes + + +[ ARM64 ] + +- Support CS_OPT_UNSIGNED +- Fix register access flags for memory instructions +- Fix UMOV vess + + +[ ARM ] + +- Update writeback for STR_POST_REG + + +[ M68K ] + +- Store correct register value in op.reg_pair + + +[ PowerPC ] + +- BDZLA is absolute branch + + +[ SystemZ ] + +- Fix truncated 64bit imm operand +- Fix base/index printing + + +[ Python ] + +- Fix skipdata struct being destroyed +- Add __repr__ for capstone.CsInsn + + +[ Java ] + +- Fix Java bindings to use pointers instead of longs + + +[ Ocaml ] + +- Fix x86_op record + + --------------------------------- Version 4.0.1: January 10th, 2019 diff --git a/MCInst.c b/MCInst.c index 2d0aec924c..4c39f999fd 100644 --- a/MCInst.c +++ b/MCInst.c @@ -21,6 +21,7 @@ void MCInst_Init(MCInst *inst) for (i = 0; i < 48; i++) { inst->Operands[i].Kind = kInvalid; + inst->Operands[i].ImmVal = 0; } inst->Opcode = 0; diff --git a/Makefile b/Makefile index 9e06902037..83677570bb 100644 --- a/Makefile +++ b/Makefile @@ -417,23 +417,27 @@ endif $(INSTALL_DATA) include/capstone/*.h $(DESTDIR)$(INCDIR)/$(LIBNAME) mkdir -p $(PKGCFGDIR) $(INSTALL_DATA) $(PKGCFGF) $(PKGCFGDIR) +ifeq (,$(findstring yes,$(CAPSTONE_BUILD_CORE_ONLY))) mkdir -p $(BINDIR) $(INSTALL_LIB) cstool/cstool $(BINDIR) +endif uninstall: rm -rf $(DESTDIR)$(INCDIR)/$(LIBNAME) rm -f $(LIBDIR)/lib$(LIBNAME).* rm -f $(PKGCFGDIR)/$(LIBNAME).pc +ifeq (,$(findstring yes,$(CAPSTONE_BUILD_CORE_ONLY))) rm -f $(BINDIR)/cstool +endif clean: rm -f $(LIBOBJ) rm -f $(BLDIR)/lib$(LIBNAME).* $(BLDIR)/$(LIBNAME).pc rm -f $(PKGCFGF) [ "${ANDROID}" = "1" ] && rm -rf android-ndk-* || true - $(MAKE) -C cstool clean ifeq (,$(findstring yes,$(CAPSTONE_BUILD_CORE_ONLY))) + $(MAKE) -C cstool clean $(MAKE) -C tests clean $(MAKE) -C suite/fuzz clean rm -f $(BLDIR)/tests/lib$(LIBNAME).$(EXT) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index e69de29bb2..f0102506f5 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -0,0 +1,4 @@ +This release 4.0.2 is dedicated to my dad! + +Without him, I would not work in computing field, let alone writing any code +or making contribution to the cyber security community. diff --git a/SPONSORS.TXT b/SPONSORS.TXT index e737e2abf5..f8f67564e6 100644 --- a/SPONSORS.TXT +++ b/SPONSORS.TXT @@ -1,3 +1,11 @@ +* Version 4.0.2 - May 08th, 2020 + +Release 4.0.2 was sponsored by the following companies (in no particular order). + +- Senrio: https://senr.io +- Catena Cyber: https://catenacyber.fr + +------------------------------------ * Version 4.0.1 - January 10th, 2019 Release 4.0.1 was sponsored by the following companies (in no particular order). diff --git a/arch/M680X/M680XDisassembler.c b/arch/M680X/M680XDisassembler.c index ef02fbcf90..bb418de361 100644 --- a/arch/M680X/M680XDisassembler.c +++ b/arch/M680X/M680XDisassembler.c @@ -2121,11 +2121,6 @@ static const cpu_tables g_cpu_tables[] = { }, }; -static const char *s_cpu_type[] = { - "INVALID", "6301", "6309", "6800", "6801", "6805", "6808", - "6809", "6811", "CPU12", "HCS08", -}; - static bool m680x_setup_internals(m680x_info *info, e_cpu_type cpu_type, uint16_t address, const uint8_t *code, uint16_t code_len) @@ -2255,12 +2250,6 @@ cs_err M680X_disassembler_init(cs_struct *ud) return CS_ERR_MODE; } - if (M680X_CPU_TYPE_ENDING != ARR_SIZE(s_cpu_type)) { - CS_ASSERT(M680X_CPU_TYPE_ENDING == ARR_SIZE(s_cpu_type)); - - return CS_ERR_MODE; - } - if (M680X_CPU_TYPE_ENDING != ARR_SIZE(g_cpu_tables)) { CS_ASSERT(M680X_CPU_TYPE_ENDING == ARR_SIZE(g_cpu_tables)); diff --git a/arch/M68K/M68KDisassembler.c b/arch/M68K/M68KDisassembler.c index 42a3efdf69..714795ffb8 100644 --- a/arch/M68K/M68KDisassembler.c +++ b/arch/M68K/M68KDisassembler.c @@ -1582,7 +1582,7 @@ static void d68000_bsr_16(m68k_info *info) static void d68020_bsr_32(m68k_info *info) { LIMIT_CPU_TYPES(info, M68020_PLUS); - build_relative_branch(info, M68K_INS_BSR, 4, peek_imm_32(info)); + build_relative_branch(info, M68K_INS_BSR, 4, read_imm_32(info)); } static void d68000_btst_r(m68k_info *info) @@ -2036,8 +2036,14 @@ static void d68020_cpgen(m68k_info *info) ext->op_size.type = M68K_SIZE_TYPE_CPU; ext->op_size.cpu_size = 0; - op0 = &ext->operands[0]; - op1 = &ext->operands[1]; + // Special case - adjust direction of fmove + if ((opmode == 0x00) && ((next >> 13) & 0x1) != 0) { + op0 = &ext->operands[1]; + op1 = &ext->operands[0]; + } else { + op0 = &ext->operands[0]; + op1 = &ext->operands[1]; + } if (rm == 0 && supports_single_op && src == dst) { ext->op_count = 1; diff --git a/arch/Sparc/SparcInstPrinter.c b/arch/Sparc/SparcInstPrinter.c index da83187441..597bd1103a 100644 --- a/arch/Sparc/SparcInstPrinter.c +++ b/arch/Sparc/SparcInstPrinter.c @@ -358,7 +358,7 @@ void Sparc_printInst(MCInst *MI, SStream *O, void *Info) mnem = printAliasInstr(MI, O, Info); if (mnem) { // fixup instruction id due to the change in alias instruction - strncpy(instr, mnem, sizeof(instr)); + strncpy(instr, mnem, sizeof(instr) - 1); instr[sizeof(instr) - 1] = '\0'; // does this contains hint with a coma? p = strchr(instr, ','); diff --git a/arch/X86/X86MappingInsnOp.inc b/arch/X86/X86MappingInsnOp.inc index 6e558c6ee9..f7e2eefac1 100644 --- a/arch/X86/X86MappingInsnOp.inc +++ b/arch/X86/X86MappingInsnOp.inc @@ -10435,15 +10435,15 @@ }, { /* X86_TEST16i16, X86_INS_TEST: test{w} ax, $src */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, - { CS_AC_READ | CS_AC_WRITE, CS_AC_IGNORE, 0 } + { CS_AC_READ, CS_AC_IGNORE, 0 } }, { /* X86_TEST16mi, X86_INS_TEST: test{w} $dst, $src */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, - { CS_AC_READ | CS_AC_WRITE, CS_AC_IGNORE, 0 } + { CS_AC_READ, CS_AC_IGNORE, 0 } }, { /* X86_TEST16mi_alt, X86_INS_TEST: test{w} $dst, $src */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, - { CS_AC_READ | CS_AC_WRITE, CS_AC_IGNORE, 0 } + { CS_AC_READ, CS_AC_IGNORE, 0 } }, { /* X86_TEST16ri, X86_INS_TEST: test{w} $src1, $src2 */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, @@ -10463,15 +10463,15 @@ }, { /* X86_TEST32i32, X86_INS_TEST: test{l} eax, $src */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, - { CS_AC_READ | CS_AC_WRITE, CS_AC_IGNORE, 0 } + { CS_AC_READ, CS_AC_IGNORE, 0 } }, { /* X86_TEST32mi, X86_INS_TEST: test{l} $dst, $src */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, - { CS_AC_READ | CS_AC_WRITE, CS_AC_IGNORE, 0 } + { CS_AC_READ, CS_AC_IGNORE, 0 } }, { /* X86_TEST32mi_alt, X86_INS_TEST: test{l} $dst, $src */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, - { CS_AC_READ | CS_AC_WRITE, CS_AC_IGNORE, 0 } + { CS_AC_READ, CS_AC_IGNORE, 0 } }, { /* X86_TEST32ri, X86_INS_TEST: test{l} $src1, $src2 */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, @@ -10491,15 +10491,15 @@ }, { /* X86_TEST64i32, X86_INS_TEST: test{q} rax, $src */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, - { CS_AC_READ | CS_AC_WRITE, CS_AC_IGNORE, 0 } + { CS_AC_READ, CS_AC_IGNORE, 0 } }, { /* X86_TEST64mi32, X86_INS_TEST: test{q} $dst, $src */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, - { CS_AC_READ | CS_AC_WRITE, CS_AC_IGNORE, 0 } + { CS_AC_READ, CS_AC_IGNORE, 0 } }, { /* X86_TEST64mi32_alt, X86_INS_TEST: test{q} $dst, $src */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, - { CS_AC_READ | CS_AC_WRITE, CS_AC_IGNORE, 0 } + { CS_AC_READ, CS_AC_IGNORE, 0 } }, { /* X86_TEST64ri32, X86_INS_TEST: test{q} $src1, $src2 */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, diff --git a/arch/X86/X86MappingInsnOp_reduce.inc b/arch/X86/X86MappingInsnOp_reduce.inc index 28b1872915..808c1fa2f9 100644 --- a/arch/X86/X86MappingInsnOp_reduce.inc +++ b/arch/X86/X86MappingInsnOp_reduce.inc @@ -5623,15 +5623,15 @@ }, { /* X86_TEST16i16, X86_INS_TEST: test{w} ax, $src */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, - { CS_AC_READ | CS_AC_WRITE, CS_AC_IGNORE, 0 } + { CS_AC_READ, CS_AC_IGNORE, 0 } }, { /* X86_TEST16mi, X86_INS_TEST: test{w} $dst, $src */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, - { CS_AC_READ | CS_AC_WRITE, CS_AC_IGNORE, 0 } + { CS_AC_READ, CS_AC_IGNORE, 0 } }, { /* X86_TEST16mi_alt, X86_INS_TEST: test{w} $dst, $src */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, - { CS_AC_READ | CS_AC_WRITE, CS_AC_IGNORE, 0 } + { CS_AC_READ, CS_AC_IGNORE, 0 } }, { /* X86_TEST16ri, X86_INS_TEST: test{w} $src1, $src2 */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, @@ -5651,15 +5651,15 @@ }, { /* X86_TEST32i32, X86_INS_TEST: test{l} eax, $src */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, - { CS_AC_READ | CS_AC_WRITE, CS_AC_IGNORE, 0 } + { CS_AC_READ, CS_AC_IGNORE, 0 } }, { /* X86_TEST32mi, X86_INS_TEST: test{l} $dst, $src */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, - { CS_AC_READ | CS_AC_WRITE, CS_AC_IGNORE, 0 } + { CS_AC_READ, CS_AC_IGNORE, 0 } }, { /* X86_TEST32mi_alt, X86_INS_TEST: test{l} $dst, $src */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, - { CS_AC_READ | CS_AC_WRITE, CS_AC_IGNORE, 0 } + { CS_AC_READ, CS_AC_IGNORE, 0 } }, { /* X86_TEST32ri, X86_INS_TEST: test{l} $src1, $src2 */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, @@ -5679,15 +5679,15 @@ }, { /* X86_TEST64i32, X86_INS_TEST: test{q} rax, $src */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, - { CS_AC_READ | CS_AC_WRITE, CS_AC_IGNORE, 0 } + { CS_AC_READ, CS_AC_IGNORE, 0 } }, { /* X86_TEST64mi32, X86_INS_TEST: test{q} $dst, $src */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, - { CS_AC_READ | CS_AC_WRITE, CS_AC_IGNORE, 0 } + { CS_AC_READ, CS_AC_IGNORE, 0 } }, { /* X86_TEST64mi32_alt, X86_INS_TEST: test{q} $dst, $src */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, - { CS_AC_READ | CS_AC_WRITE, CS_AC_IGNORE, 0 } + { CS_AC_READ, CS_AC_IGNORE, 0 } }, { /* X86_TEST64ri32, X86_INS_TEST: test{q} $src1, $src2 */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, @@ -5707,15 +5707,15 @@ }, { /* X86_TEST8i8, X86_INS_TEST: test{b} al, $src */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, - { CS_AC_READ | CS_AC_WRITE, CS_AC_IGNORE, 0 } + { CS_AC_READ, CS_AC_IGNORE, 0 } }, { /* X86_TEST8mi, X86_INS_TEST: test{b} $dst, $src */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, - { CS_AC_READ | CS_AC_WRITE, CS_AC_IGNORE, 0 } + { CS_AC_READ, CS_AC_IGNORE, 0 } }, { /* X86_TEST8mi_alt, X86_INS_TEST: test{b} $dst, $src */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, - { CS_AC_READ | CS_AC_WRITE, CS_AC_IGNORE, 0 } + { CS_AC_READ, CS_AC_IGNORE, 0 } }, { /* X86_TEST8ri, X86_INS_TEST: test{b} $src1, $src2 */ X86_EFLAGS_RESET_OF | X86_EFLAGS_MODIFY_SF | X86_EFLAGS_MODIFY_ZF | X86_EFLAGS_UNDEFINED_AF | X86_EFLAGS_MODIFY_PF | X86_EFLAGS_RESET_CF, diff --git a/bindings/Makefile b/bindings/Makefile index 7ecada8e03..16dbb3a1e1 100644 --- a/bindings/Makefile +++ b/bindings/Makefile @@ -13,7 +13,7 @@ TEST_SYSZ = $(TMPDIR)/test_systemz TEST_X86 = $(TMPDIR)/test_x86 TEST_XCORE = $(TMPDIR)/test_xcore -PYTHON2 = python +PYTHON2 ?= python .PHONY: all expected python java ocaml diff --git a/bindings/README b/bindings/README index d7de6d4265..63be0e01a8 100644 --- a/bindings/README +++ b/bindings/README @@ -47,6 +47,10 @@ More bindings created & maintained by the community are available as followings. https://github.com/ibabushkin/hapstone +- CL-Capstone: Common Lisp bindings (by GrammaTech). + + https://github.com/GrammaTech/cl-capstone + - Emacs-capstone: Emacs (elisp) binding (by Bas Alberts) https://github.com/collarchoke/emacs-capstone diff --git a/bindings/java/Makefile b/bindings/java/Makefile index 25a87e76f9..32f50bedc4 100644 --- a/bindings/java/Makefile +++ b/bindings/java/Makefile @@ -20,7 +20,7 @@ else endif endif -PYTHON2 = python +PYTHON2 ?= python CAPSTONE_JAVA = Capstone.java Arm_const.java Arm64_const.java Mips_const.java \ X86_const.java Xcore_const.java Ppc_const.java Sparc_const.java\ diff --git a/bindings/ocaml/Makefile b/bindings/ocaml/Makefile index 5c70db4af4..0ce12a325a 100644 --- a/bindings/ocaml/Makefile +++ b/bindings/ocaml/Makefile @@ -3,7 +3,7 @@ LIB = capstone FLAGS = '-Wall -Wextra -Wwrite-strings' -PYTHON2 = python +PYTHON2 ?= python all: arm_const.cmxa arm64_const.cmxa m680x_const.cmxa mips_const.cmxa ppc_const.cmxa sparc_const.cmxa sysz_const.cmxa x86_const.cmxa xcore_const.cmxa arm.cmxa arm64.cmxa m680x.cmxa mips.cmxa ppc.cmxa x86.cmxa sparc.cmxa systemz.cmxa xcore.cmxa capstone.cmxa test_basic.cmx test_detail.cmx test_x86.cmx test_arm.cmx test_arm64.cmx test_mips.cmx test_ppc.cmx test_sparc.cmx test_systemz.cmx test_xcore.cmx test_m680x.cmx ocaml.o ocamlopt -o test_basic -ccopt $(FLAGS) ocaml.o capstone.cmx test_basic.cmx -cclib -l$(LIB) diff --git a/bindings/python/Makefile b/bindings/python/Makefile index 0002a43658..e450fcc152 100644 --- a/bindings/python/Makefile +++ b/bindings/python/Makefile @@ -1,5 +1,5 @@ -PYTHON2 = python -PYTHON3 = python3 +PYTHON2 ?= python +PYTHON3 ?= python3 .PHONY: gen_const install install3 install_cython sdist sdist3 bdist bdist3 clean check diff --git a/bindings/python/build_wheel.sh b/bindings/python/build_wheel.sh new file mode 100755 index 0000000000..39ffcb37e0 --- /dev/null +++ b/bindings/python/build_wheel.sh @@ -0,0 +1,15 @@ +#!/bin/bash +set -e -x + +cd bindings/python +sudo rm /usr/bin/python && sudo ln -s /opt/python/cp27-cp27m/bin/python /usr/bin/python; python -V + +# Compile wheels +if [ -f /opt/python/cp36-cp36m/bin/python ];then + /opt/python/cp36-cp36m/bin/python setup.py bdist_wheel +else + python3 setup.py bdist_wheel +fi +cd dist +auditwheel repair *.whl +mv -f wheelhouse/*.whl . diff --git a/bindings/python/capstone/__init__.py b/bindings/python/capstone/__init__.py index 191aea87ea..757dc7d6c8 100644 --- a/bindings/python/capstone/__init__.py +++ b/bindings/python/capstone/__init__.py @@ -536,6 +536,9 @@ def __init__(self, cs, all_info): self._raw.detail = ctypes.pointer(all_info.detail._type_()) ctypes.memmove(ctypes.byref(self._raw.detail[0]), ctypes.byref(all_info.detail[0]), ctypes.sizeof(type(all_info.detail[0]))) + def __repr__(self): + return '' % (self.address, self.bytes.hex(), self.mnemonic, self.op_str) + # return instruction's ID. @property def id(self): diff --git a/bindings/python/setup.cfg b/bindings/python/setup.cfg new file mode 100644 index 0000000000..2a9acf13da --- /dev/null +++ b/bindings/python/setup.cfg @@ -0,0 +1,2 @@ +[bdist_wheel] +universal = 1 diff --git a/bindings/python/setup.py b/bindings/python/setup.py index 55934b5e09..103e4637f8 100755 --- a/bindings/python/setup.py +++ b/bindings/python/setup.py @@ -207,6 +207,48 @@ def run(self): # https://www.python.org/dev/peps/pep-0425/ sys.argv.insert(idx + 1, name.replace('.', '_').replace('-', '_')) +long_desc = ''' +Capstone is a disassembly framework with the target of becoming the ultimate +disasm engine for binary analysis and reversing in the security community. + +Created by Nguyen Anh Quynh, then developed and maintained by a small community, +Capstone offers some unparalleled features: + +- Support multiple hardware architectures: ARM, ARM64 (ARMv8), Mips, PPC, Sparc, + SystemZ, XCore and X86 (including X86_64). + +- Having clean/simple/lightweight/intuitive architecture-neutral API. + +- Provide details on disassembled instruction (called "decomposer" by others). + +- Provide semantics of the disassembled instruction, such as list of implicit + registers read & written. + +- Implemented in pure C language, with lightweight wrappers for C++, C#, Go, + Java, NodeJS, Ocaml, Python, Ruby & Vala ready (available in main code, + or provided externally by the community). + +- Native support for all popular platforms: Windows, Mac OSX, iOS, Android, + Linux, *BSD, Solaris, etc. + +- Thread-safe by design. + +- Special support for embedding into firmware or OS kernel. + +- High performance & suitable for malware analysis (capable of handling various + X86 malware tricks). + +- Distributed under the open source BSD license. + +Further information is available at http://www.capstone-engine.org + + +[License] + +This project is released under the BSD license. If you redistribute the binary +or source code of Capstone, please attach file LICENSE.TXT with your products. +''' + setup( provides=['capstone'], packages=['capstone'], @@ -215,9 +257,14 @@ def run(self): author='Nguyen Anh Quynh', author_email='aquynh@gmail.com', description='Capstone disassembly engine', - url='http://www.capstone-engine.org', + long_description=long_desc, + long_description_content_type="text/markdown", + url='https://www.capstone-engine.org', python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Developers', + 'Topic :: Software Development :: Build Tools', 'License :: OSI Approved :: BSD License', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', @@ -227,6 +274,7 @@ def run(self): cmdclass=cmdclass, zip_safe=True, include_package_data=True, + is_pure=False, package_data={ "capstone": ["lib/*", "include/capstone/*"], } diff --git a/capstone.pc.in b/capstone.pc.in index 69541b248b..b8ea3d30a5 100644 --- a/capstone.pc.in +++ b/capstone.pc.in @@ -1,6 +1,6 @@ prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} -libdir=${prefix}/lib@LIBSUFFIX@ +libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ includedir=${prefix}/include/capstone Name: capstone diff --git a/cs.c b/cs.c index 98f30f769f..2ee78f1908 100644 --- a/cs.c +++ b/cs.c @@ -576,7 +576,7 @@ static void fill_insn(struct cs_struct *handle, cs_insn *insn, char *buffer, MCI while(tmp) { if (tmp->insn.id == insn->id) { // found this instruction, so copy its mnemonic - (void)strncpy(insn->mnemonic, tmp->insn.mnemonic, sizeof(insn->mnemonic) - 1); + (void)strncpy(insn->mnemonic, tmp->insn.mnemonic, sizeof(insn->mnemonic)); insn->mnemonic[sizeof(insn->mnemonic) - 1] = '\0'; break; } diff --git a/cstool/cstool.c b/cstool/cstool.c index 89afc9aa22..04741de35c 100644 --- a/cstool/cstool.c +++ b/cstool/cstool.c @@ -466,12 +466,16 @@ int main(int argc, char **argv) putchar(' '); printf("%02x", insn[i].bytes[j]); } - // X86 instruction size is variable. + // X86 and s390 instruction sizes are variable. // align assembly instruction after the opcode if (arch == CS_ARCH_X86) { for (; j < 16; j++) { printf(" "); } + } else if (arch == CS_ARCH_SYSZ) { + for (; j < 6; j++) { + printf(" "); + } } printf(" %s\t%s\n", insn[i].mnemonic, insn[i].op_str); diff --git a/include/capstone/capstone.h b/include/capstone/capstone.h index 23c13d5f95..0f0596d16f 100644 --- a/include/capstone/capstone.h +++ b/include/capstone/capstone.h @@ -60,6 +60,65 @@ extern "C" { #define CS_VERSION_MINOR CS_API_MINOR #define CS_VERSION_EXTRA 2 +/// Macro for meta programming. +/// Meant for projects using Capstone and need to support multiple +/// versions of it. +/// These macros replace several instances of the old "ARM64" with +/// the new "AArch64" name depending on the CS version. +#if CS_NEXT_VERSION < 6 +#define CS_AARCH64(x) ARM64##x +#else +#define CS_AARCH64(x) AArch64##x +#endif + +#if CS_NEXT_VERSION < 6 +#define CS_AARCH64pre(x) x##ARM64 +#else +#define CS_AARCH64pre(x) x##AARCH64 +#endif + +#if CS_NEXT_VERSION < 6 +#define CS_AARCH64CC(x) ARM64_CC##x +#else +#define CS_AARCH64CC(x) AArch64CC##x +#endif + +#if CS_NEXT_VERSION < 6 +#define CS_AARCH64_VL_(x) ARM64_VAS_##x +#else +#define CS_AARCH64_VL_(x) AArch64Layout_VL_##x +#endif + +#if CS_NEXT_VERSION < 6 +#define CS_aarch64_ arm64 +#else +#define CS_aarch64_ aarch64 +#endif + +#if CS_NEXT_VERSION < 6 +#define CS_aarch64(x) arm64##x +#else +#define CS_aarch64(x) aarch64##x +#endif + +#if CS_NEXT_VERSION < 6 +#define CS_aarch64_op() cs_arm64_op +#define CS_aarch64_reg() arm64_reg +#define CS_aarch64_cc() arm64_cc +#define CS_cs_aarch64() cs_arm64 +#define CS_aarch64_extender() arm64_extender +#define CS_aarch64_shifter() arm64_shifter +#define CS_aarch64_vas() arm64_vas +#else +#define CS_aarch64_op() cs_aarch64_op +#define CS_aarch64_reg() aarch64_reg +#define CS_aarch64_cc() AArch64CC_CondCode +#define CS_cs_aarch64() cs_aarch64 +#define CS_aarch64_extender() aarch64_extender +#define CS_aarch64_shifter() aarch64_shifter +#define CS_aarch64_vas() AArch64Layout_VectorLayout +#endif + /// Macro to create combined version which can be compared to /// result of cs_version() API. #define CS_MAKE_VERSION(major, minor) ((major << 8) + minor) @@ -120,7 +179,7 @@ typedef enum cs_mode { CS_MODE_M68K_030 = 1 << 4, ///< M68K 68030 mode CS_MODE_M68K_040 = 1 << 5, ///< M68K 68040 mode CS_MODE_M68K_060 = 1 << 6, ///< M68K 68060 mode - CS_MODE_BIG_ENDIAN = 1 << 31, ///< big-endian mode + CS_MODE_BIG_ENDIAN = 1U << 31, ///< big-endian mode CS_MODE_MIPS32 = CS_MODE_32, ///< Mips32 ISA (Mips) CS_MODE_MIPS64 = CS_MODE_64, ///< Mips64 ISA (Mips) CS_MODE_M680X_6301 = 1 << 1, ///< M680X Hitachi 6301,6303 mode diff --git a/include/capstone/m68k.h b/include/capstone/m68k.h index 76de25764a..41e23f3883 100644 --- a/include/capstone/m68k.h +++ b/include/capstone/m68k.h @@ -150,6 +150,12 @@ typedef struct m68k_op_br_disp { uint8_t disp_size; ///< Size from m68k_op_br_disp_size type above } m68k_op_br_disp; +/// Register pair in one operand. +typedef struct cs_m68k_op_reg_pair { + m68k_reg reg_0; + m68k_reg reg_1; +} cs_m68k_op_reg_pair; + /// Instruction operand typedef struct cs_m68k_op { union { @@ -157,10 +163,7 @@ typedef struct cs_m68k_op { double dimm; ///< double imm float simm; ///< float imm m68k_reg reg; ///< register value for REG operand - struct { ///< register pair in one operand - m68k_reg reg_0; - m68k_reg reg_1; - } reg_pair; + cs_m68k_op_reg_pair reg_pair; ///< register pair in one operand }; m68k_op_mem mem; ///< data when operand is targeting memory diff --git a/include/capstone/mips.h b/include/capstone/mips.h index f10c303329..339445611c 100644 --- a/include/capstone/mips.h +++ b/include/capstone/mips.h @@ -240,7 +240,7 @@ typedef struct mips_op_mem { typedef struct cs_mips_op { mips_op_type type; ///< operand type union { - mips_reg reg; ///< register value for REG operand + mips_reg reg; ///< register id for REG operand int64_t imm; ///< immediate value for IMM operand mips_op_mem mem; ///< base/index/scale/disp value for MEM operand }; diff --git a/tests/test_arm64.c b/tests/test_arm64.c index d0111ec916..1237ea7406 100644 --- a/tests/test_arm64.c +++ b/tests/test_arm64.c @@ -1,6 +1,7 @@ /* Capstone Disassembler Engine */ /* By Nguyen Anh Quynh , 2013-2019 */ +#include #include #include @@ -222,9 +223,27 @@ static void test() } } +void test_macros() { + assert(CS_AARCH64(_INS_BL) == ARM64_INS_BL); + assert(CS_AARCH64pre(CS_ARCH_) == CS_ARCH_ARM64); + assert(CS_AARCH64CC(_AL) == ARM64_CC_AL); + assert(CS_AARCH64_VL_(16B) == ARM64_VAS_16B); + cs_detail detail = { 0 }; + CS_cs_aarch64() arm64_detail = { 0 }; + detail.arm64 = arm64_detail; + CS_aarch64_op() op = { 0 }; + detail.CS_aarch64_.operands[0] = op; + CS_aarch64_reg() reg = 1; + CS_aarch64_cc() cc = ARM64_CC_AL; + CS_aarch64_extender() arm64_extender = ARM64_EXT_SXTB; + CS_aarch64_shifter() arm64_shifter = ARM64_SFT_LSL; + CS_aarch64_vas() arm64_vas = ARM64_VAS_16B; +} + int main() { test(); + test_macros(); return 0; }