diff --git a/.github/workflows/CrossBuilds.yml b/.github/workflows/CrossBuilds.yml new file mode 100644 index 0000000000..ab22492773 --- /dev/null +++ b/.github/workflows/CrossBuilds.yml @@ -0,0 +1,204 @@ +name: Cross Build Tests +on: + push: + paths-ignore: + - ".gitignore" + - "docs/**" + - "ChangeLog" + - "CREDITS.TXT" + - "COMPILE.TXT" + - "COMPILE_CMAKE.TXT" + - "COMPILE_MSVC.TXT" + - "HACK.TXT" + - "LICENSE.TXT" + - "LICENSE_LLVM.TXT" + - "README.md" + - "RELEASE_NOTES" + - "SPONSORS.TXT" + pull_request: + +# Stop previous runs on the same branch on new push +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + CI: true + +jobs: + Linux: + runs-on: ${{ matrix.config.os }} + name: ${{ matrix.config.name }} + strategy: + fail-fast: false + matrix: + config: + - { + name: 'QEMU Linux s390x', + os: ubuntu-24.04, + system: 'Linux', + processor: 's390x', + cc: 's390x-linux-gnu-gcc', + cxx: 's390x-linux-gnu-g++', + sysroot: '/usr/s390x-linux-gnu', + qemu: 'qemu-s390x-static', + build_type: 'Debug', + packages: 'gcc-s390x-linux-gnu g++-s390x-linux-gnu binutils-s390x-linux-gnu libc6-dev-s390x-cross qemu-user-static', + build_tests: 'ON', + diet_build: 'OFF', + toolchain_file: 'toolchain.cmake', + } + - { + name: 'QEMU Linux MIPS 32 BE', + os: ubuntu-24.04, + system: 'Linux', + processor: 'mips', + cc: 'mips-linux-gnu-gcc', + cxx: 'mips-linux-gnu-g++', + sysroot: '/usr/mips-linux-gnu', + qemu: 'qemu-mips-static', + build_type: 'Debug', + packages: 'gcc-mips-linux-gnu g++-mips-linux-gnu binutils-mips-linux-gnu libc6-dev-mips-cross qemu-user-static', + build_tests: 'ON', + diet_build: 'OFF', + toolchain_file: 'toolchain.cmake', + } + - { + name: 'QEMU Linux Mips64el', + os: ubuntu-24.04, + system: 'Linux', + processor: 'mips64el', + cc: 'mips64el-linux-gnuabi64-gcc', + cxx: 'mips64el-linux-gnuabi64-g++', + sysroot: '/usr/mips64el-linux-gnuabi64', + qemu: 'qemu-mips64el-static', + build_type: 'Debug', + packages: 'gcc-mips64el-linux-gnuabi64 g++-mips64el-linux-gnuabi64 binutils-mips64el-linux-gnuabi64 libc6-dev-mips64el-cross qemu-user-static', + build_tests: 'ON', + diet_build: 'OFF', + toolchain_file: 'toolchain.cmake', + } + - { + name: 'QEMU Linux PPC64', + os: ubuntu-24.04, + system: 'Linux', + processor: 'ppc64', + cc: 'powerpc64-linux-gnu-gcc', + cxx: 'powerpc64-linux-gnu-g++', + sysroot: '/usr/powerpc64-linux-gnu', + qemu: 'qemu-ppc64-static', + build_type: 'Debug', + packages: 'gcc-powerpc64-linux-gnu g++-powerpc64-linux-gnu binutils-powerpc64-linux-gnu libc6-dev-ppc64-cross qemu-user-static', + build_tests: 'ON', + diet_build: 'OFF', + toolchain_file: 'toolchain.cmake', + } + - { + name: 'QEMU Linux ARM', + os: ubuntu-24.04, + system: 'Linux', + processor: 'arm', + cc: 'arm-linux-gnueabihf-gcc', + cxx: 'arm-linux-gnueabihf-g++', + sysroot: '/usr/arm-linux-gnueabihf', + qemu: 'qemu-arm-static', + build_type: 'Debug', + packages: 'gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf binutils-arm-linux-gnueabihf libc6-armhf-cross libc6-dev-armhf-cross qemu-user-static', + build_tests: 'ON', + diet_build: 'OFF', + toolchain_file: 'toolchain.cmake', + } + - { + name: '[BUILD ONLY] Windows i686 mingw', + os: ubuntu-24.04, + system: 'Windows', + processor: 'i686', + cc: 'i686-w64-mingw32-gcc', + cxx: 'i686-w64-mingw32-g++', + rc: 'i686-w64-mingw32-windres', + find_root: '/usr/i686-w64-mingw32', + build_type: 'Debug', + skip_tests: true, + packages: 'gcc-mingw-w64-i686 g++-mingw-w64-i686 mingw-w64-tools', + build_tests: 'OFF', + diet_build: 'OFF', + toolchain_file: 'toolchain.cmake', + } + - { + name: '[BUILD ONLY] Android 35 (arm64_v8a) NDK 29', + os: ubuntu-24.04, + system: 'Android', + processor: 'aarch64', + build_option: '-DANDROID_PLATFORM=android-35 -DANDROID_ABI=arm64-v8a', + build_type: 'Debug', + # QEMU alone can't emulate the binaries, because the NDK doesn't + # provide dynamic linker. + skip_tests: true, + packages: 'qemu-user-static unzip wget', + ndk_version: 'r29', + build_tests: 'OFF', + diet_build: 'OFF', + toolchain_file: 'ndk/build/cmake/android.toolchain.cmake', + } + + steps: + - uses: actions/checkout@v6 + + - name: Install cross build dependencies + if: ${{ matrix.config.packages != '' }} + env: + packages: ${{ matrix.config.packages }} + run: | + sudo apt-get update + sudo apt-get install -y ${packages} + + - name: Setup Android NDK + if: contains(matrix.config.name, 'Android') + env: + ndk_version: ${{ matrix.config.ndk_version }} + run: | + wget -q https://dl.google.com/android/repository/android-ndk-${ndk_version}-linux.zip + unzip -q android-ndk-${ndk_version}-linux.zip + mv android-ndk-${ndk_version} ndk + cat ndk/source.properties + + - name: cmake (cross build) + env: + system: ${{ matrix.config.system }} + processor: ${{ matrix.config.processor }} + cc: ${{ matrix.config.cc }} + cxx: ${{ matrix.config.cxx }} + rc: ${{ matrix.config.rc }} + find_root: ${{ matrix.config.find_root }} + sysroot: ${{ matrix.config.sysroot }} + qemu: ${{ matrix.config.qemu }} + build_option: ${{ matrix.config.build_option }} + build_type: ${{ matrix.config.build_type }} + build_tests: ${{ matrix.config.build_tests }} + diet_build: ${{ matrix.config.diet_build }} + toolchain_file: ${{ matrix.config.toolchain_file }} + run: | + cmake -DCMAKE_BUILD_TYPE=${build_type} \ + -DBUILD_STATIC_LIBS=ON \ + -DBUILD_SHARED_LIBS=OFF \ + -DCAPSTONE_BUILD_TESTS=${build_tests} \ + -DCAPSTONE_BUILD_CSTOOL=ON \ + -DCAPSTONE_BUILD_CSTEST=OFF \ + -S . \ + -DCAPSTONE_BUILD_DIET=${diet_build} \ + -DCMAKE_TOOLCHAIN_FILE=${toolchain_file} \ + ${build_option} \ + -B build + cmake --build build --config ${build_type} --parallel + + - name: C tests + if: ${{ matrix.config.skip_tests != true }} + run: | + ctest --test-dir build --output-on-failure -R '^capstone_' + + - name: cstest + shell: 'script -q -e -c "bash {0}"' + run: | + cd suite/cstest && ./build_cstest.sh; + python cstest_report.py -D -t build/cstest -d ../MC; + python cstest_report.py -D -t build/cstest -f issues.cs; cd ..; diff --git a/arch/M68K/M68KInstPrinter.c b/arch/M68K/M68KInstPrinter.c index 061edb30a7..2e1548fdba 100644 --- a/arch/M68K/M68KInstPrinter.c +++ b/arch/M68K/M68KInstPrinter.c @@ -154,8 +154,8 @@ static void printAddressingMode(SStream* O, unsigned int pc, const cs_m68k* inst case M68K_AM_REGI_ADDR_PRE_DEC: SStream_concat(O, "-(a%d)", (op->reg - M68K_REG_A0)); break; case M68K_AM_REGI_ADDR_DISP: SStream_concat(O, "%s$%x(a%d)", op->mem.disp < 0 ? "-" : "", abs(op->mem.disp), (op->mem.base_reg - M68K_REG_A0)); break; case M68K_AM_PCI_DISP: SStream_concat(O, "$%x(pc)", pc + 2 + op->mem.disp); break; - case M68K_AM_ABSOLUTE_DATA_SHORT: SStream_concat(O, "$%x.w", op->imm); break; - case M68K_AM_ABSOLUTE_DATA_LONG: SStream_concat(O, "$%x.l", op->imm); break; + case M68K_AM_ABSOLUTE_DATA_SHORT: SStream_concat(O, "$%x.w", (unsigned int)op->imm); break; + case M68K_AM_ABSOLUTE_DATA_LONG: SStream_concat(O, "$%x.l", (unsigned int)op->imm); break; case M68K_AM_IMMEDIATE: if (inst->op_size.type == M68K_SIZE_TYPE_FPU) { #if defined(_KERNEL_MODE) @@ -172,7 +172,7 @@ static void printAddressingMode(SStream* O, unsigned int pc, const cs_m68k* inst break; #endif } - SStream_concat(O, "#$%x", op->imm); + SStream_concat(O, "#$%x", (unsigned int)op->imm); break; case M68K_AM_PCI_INDEX_8_BIT_DISP: SStream_concat(O, "$%x(pc,%s%s.%c)", pc + 2 + op->mem.disp, s_spacing, getRegName(op->mem.index_reg), op->mem.index_size ? 'l' : 'w'); @@ -287,7 +287,7 @@ void M68K_printInst(MCInst* MI, SStream* O, void* PrinterInfo) if (MI->Opcode == M68K_INS_INVALID) { if (ext->op_count) - SStream_concat(O, "dc.w $%x", ext->operands[0].imm); + SStream_concat(O, "dc.w $%x", (unsigned int)ext->operands[0].imm); else SStream_concat(O, "dc.w $"); return; diff --git a/arch/MOS65XX/MOS65XXDisassembler.c b/arch/MOS65XX/MOS65XXDisassembler.c index c3d8c429b5..2723f6fa60 100644 --- a/arch/MOS65XX/MOS65XXDisassembler.c +++ b/arch/MOS65XX/MOS65XXDisassembler.c @@ -330,7 +330,7 @@ void MOS65XX_printInst(MCInst *MI, struct SStream *O, void *PrinterInfo) value = 3 + (signed short)value; SStream_concat(O, " %s%04x", prefix, - (MI->address + value) & 0xffff); + (unsigned int)((MI->address + value) & 0xffff)); break; case MOS65XX_AM_ABS_IND: @@ -375,16 +375,16 @@ void MOS65XX_printInst(MCInst *MI, struct SStream *O, void *PrinterInfo) case MOS65XX_AM_BLOCK: SStream_concat(O, " %s%02x, %s%02x", - prefix, MI->Operands[0].ImmVal, - prefix, MI->Operands[1].ImmVal); + prefix, (unsigned int)MI->Operands[0].ImmVal, + prefix, (unsigned int)MI->Operands[1].ImmVal); break; case MOS65XX_AM_ZP_REL: value = 3 + (signed char)MI->Operands[1].ImmVal; /* BBR0, zp, rel and BBS0, zp, rel */ SStream_concat(O, " %s%02x, %s%04x", - prefix, MI->Operands[0].ImmVal, - prefix, (MI->address + value) & 0xffff); + prefix, (unsigned int)MI->Operands[0].ImmVal, + prefix, (unsigned int)((MI->address + value) & 0xffff)); break; } diff --git a/arch/X86/X86ATTInstPrinter.c b/arch/X86/X86ATTInstPrinter.c index b2f8412859..1dead566d6 100644 --- a/arch/X86/X86ATTInstPrinter.c +++ b/arch/X86/X86ATTInstPrinter.c @@ -707,7 +707,7 @@ static void printMemReference(MCInst *MI, unsigned Op, SStream *O) MCOperand *IndexReg = MCInst_getOperand(MI, Op + X86_AddrIndexReg); MCOperand *DispSpec = MCInst_getOperand(MI, Op + X86_AddrDisp); MCOperand *SegReg = MCInst_getOperand(MI, Op + X86_AddrSegmentReg); - uint64_t ScaleVal; + unsigned int ScaleVal; int segreg; int64_t DispVal = 1; @@ -769,7 +769,7 @@ static void printMemReference(MCInst *MI, unsigned Op, SStream *O) if (MCOperand_getReg(IndexReg) && MCOperand_getReg(IndexReg) != X86_EIZ) { SStream_concat0(O, ", "); _printOperand(MI, Op + X86_AddrIndexReg, O); - ScaleVal = MCOperand_getImm(MCInst_getOperand(MI, Op + X86_AddrScaleAmt)); + ScaleVal = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, Op + X86_AddrScaleAmt)); if (MI->csh->detail) MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = (int)ScaleVal; if (ScaleVal != 1) { diff --git a/arch/X86/X86IntelInstPrinter.c b/arch/X86/X86IntelInstPrinter.c index 05d4141bad..eb1c290b56 100644 --- a/arch/X86/X86IntelInstPrinter.c +++ b/arch/X86/X86IntelInstPrinter.c @@ -929,7 +929,7 @@ static void printMemReference(MCInst *MI, unsigned Op, SStream *O) { bool NeedPlus = false; MCOperand *BaseReg = MCInst_getOperand(MI, Op + X86_AddrBaseReg); - uint64_t ScaleVal = MCOperand_getImm(MCInst_getOperand(MI, Op + X86_AddrScaleAmt)); + unsigned int ScaleVal = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, Op + X86_AddrScaleAmt)); MCOperand *IndexReg = MCInst_getOperand(MI, Op + X86_AddrIndexReg); MCOperand *DispSpec = MCInst_getOperand(MI, Op + X86_AddrDisp); MCOperand *SegReg = MCInst_getOperand(MI, Op + X86_AddrSegmentReg); diff --git a/suite/cstest/issues.cs b/suite/cstest/issues.cs index 5aee561a49..9dd16c855b 100644 --- a/suite/cstest/issues.cs +++ b/suite/cstest/issues.cs @@ -253,6 +253,22 @@ 0xf2,0x1f,0x54,0x80 == fmove.d (a7)+, fp1 0x4e,0x75 == rts +!# issue M68K printer integer immediates on 32-bit big endian hosts +!# CS_ARCH_M68K, CS_MODE_BIG_ENDIAN | CS_MODE_M68K_040, None +0x00,0x80,0x12,0x34,0x56,0x78 == ori.l #$12345678, d0 + +!# issue M68K printer absolute long addresses on 32-bit big endian hosts +!# CS_ARCH_M68K, CS_MODE_BIG_ENDIAN | CS_MODE_M68K_040, None +0x4e,0xb9,0x12,0x34,0x56,0x78 == jsr $12345678.l + +!# issue M68K printer absolute short addresses on 32-bit big endian hosts +!# CS_ARCH_M68K, CS_MODE_BIG_ENDIAN | CS_MODE_M68K_040, None +0x4e,0xb8,0x12,0x34 == jsr $1234.w + +!# issue M68K printer invalid words on 32-bit big endian hosts +!# CS_ARCH_M68K, CS_MODE_BIG_ENDIAN | CS_MODE_M68K_040, None +0xff,0xff == dc.w $ffff + !# issue 1661 M68K invalid transfer direction in MOVEC instruction !# CS_ARCH_M68K, CS_MODE_BIG_ENDIAN | CS_MODE_M68K_040, None 0x4E,0x7A,0x00,0x02 == movec cacr, d0 @@ -627,6 +643,10 @@ !# CS_ARCH_X86, CS_MODE_64, CS_OPT_DETAIL 0x0: 0x0f,0x94,0x44,0x24,0x1f == sete byte ptr [rsp + 0x1f] ; Prefix:0x00 0x00 0x00 0x00 ; Opcode:0x0f 0x94 0x00 0x00 ; rex: 0x0 ; addr_size: 8 ; modrm: 0x44 ; disp: 0x1f ; sib: 0x24 ; sib_base: rsp ; sib_scale: 1 ; op_count: 1 ; operands[0].type: MEM ; operands[0].mem.base: REG = rsp ; operands[0].mem.disp: 0x1f ; operands[0].size: 1 ; operands[0].access: WRITE ; Registers read: rflags rsp ; EFLAGS: TEST_ZF +!# issue x86 SIB scale is encoded as log2(scale) +!# CS_ARCH_X86, CS_MODE_64, None +0x0: 0x8b,0x34,0x82 == mov esi, dword ptr [rdx + rax*4] + !# issue 1263 !# CS_ARCH_X86, CS_MODE_64, None 0x0: 0x67,0x48,0x89,0x18 == mov qword ptr [eax], rbx diff --git a/tests/test_arm64.c b/tests/test_arm64.c index f4651fc599..651434286a 100644 --- a/tests/test_arm64.c +++ b/tests/test_arm64.c @@ -248,11 +248,11 @@ void test_macros() { 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; + (void)(CS_aarch64_reg())1; + (void)(CS_aarch64_cc())ARM64_CC_AL; + (void)(CS_aarch64_extender())ARM64_EXT_SXTB; + (void)(CS_aarch64_shifter())ARM64_SFT_LSL; + (void)(CS_aarch64_vas())ARM64_VAS_16B; } int main() @@ -262,4 +262,3 @@ int main() return 0; } - diff --git a/toolchain.cmake b/toolchain.cmake new file mode 100644 index 0000000000..4ab2bcdd96 --- /dev/null +++ b/toolchain.cmake @@ -0,0 +1,41 @@ +if("$ENV{system}" STREQUAL "") + message(FATAL_ERROR "toolchain.cmake requires the system environment variable") +endif() +if("$ENV{processor}" STREQUAL "") + message(FATAL_ERROR "toolchain.cmake requires the processor environment variable") +endif() +if("$ENV{cc}" STREQUAL "") + message(FATAL_ERROR "toolchain.cmake requires the cc environment variable") +endif() +if("$ENV{cxx}" STREQUAL "") + message(FATAL_ERROR "toolchain.cmake requires the cxx environment variable") +endif() + +set(CMAKE_SYSTEM_NAME "$ENV{system}") +set(CMAKE_SYSTEM_PROCESSOR "$ENV{processor}") +set(CMAKE_C_COMPILER "$ENV{cc}") +set(CMAKE_CXX_COMPILER "$ENV{cxx}") +set(CMAKE_ASM_COMPILER "$ENV{cc}") + +if(NOT "$ENV{rc}" STREQUAL "") + set(CMAKE_RC_COMPILER "$ENV{rc}") +endif() + +if(NOT "$ENV{find_root}" STREQUAL "") + set(CMAKE_FIND_ROOT_PATH "$ENV{find_root}") +endif() + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +if("$ENV{system}" STREQUAL "Linux") + if("$ENV{sysroot}" STREQUAL "") + message(FATAL_ERROR "toolchain.cmake requires the sysroot environment variable for Linux") + endif() + if("$ENV{qemu}" STREQUAL "") + message(FATAL_ERROR "toolchain.cmake requires the qemu environment variable for Linux") + endif() + set(CMAKE_SYSROOT "$ENV{sysroot}/usr") + set(CMAKE_CROSSCOMPILING_EMULATOR "$ENV{qemu}" "-L" "$ENV{sysroot}") +endif()