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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions .github/workflows/java-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
name: Java Module CI

on:
push:
pull_request:

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

jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-24.04]

steps:
- uses: actions/checkout@v6

- uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: '21'

# - name: Setup MSVC
# if: runner.os == 'Windows'
# uses: ilammy/msvc-dev-cmd@v1
Comment on lines +27 to +30
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# - name: Setup MSVC
# if: runner.os == 'Windows'
# uses: ilammy/msvc-dev-cmd@v1


- name: Install JNA
run: |
sudo apt-get update
sudo apt-get install -y libjna-java

- name: Build and install capstone
run: |
mkdir build && cd build
cmake -DCAPSTONE_INSTALL=1 -DCAPSTONE_BUILD_SHARED_LIBS=1 -DCMAKE_INSTALL_PREFIX=/usr -DCAPSTONE_BUILD_CSTEST=ON ..
sudo cmake --build . --config Debug --target install

- name: Build java bindings
working-directory: bindings/java
run: make capstone

- name: Build cstest_java
working-directory: bindings/java/cstest_java
run: ./gradlew build installDist

- name: cstest_java integration tests
working-directory: suite/cstest/test
run: |
python3 ./integration_tests.py '../../../bindings/java/cstest_java/app/build/install/app/bin/app'

- name: cstest_java negative
run: |
for test_file in \
tests/negative/should_fail_I.yaml \
tests/negative/should_fail_II.yaml \
tests/negative/should_fail_III.yaml \
tests/negative/should_fail_IV.yaml \
tests/negative/should_fail_V.yaml \
tests/negative/should_fail_VI.yaml; do
if ./bindings/java/cstest_java/app/build/install/app/bin/app "$test_file"; then
echo "Expected failure but test passed: $test_file"
exit 1
else
echo "Correctly failed: $test_file"
fi
done

- name: cstest_java MC
run: |
./bindings/java/cstest_java/app/build/install/app/bin/app tests/MC/

- name: cstest_java details
run: |
./bindings/java/cstest_java/app/build/install/app/bin/app tests/details/

- name: cstest_java issues
run: |
./bindings/java/cstest_java/app/build/install/app/bin/app tests/issues/

- name: cstest_java features
run: |
./bindings/java/cstest_java/app/build/install/app/bin/app tests/features/
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
files_to_format.txt
.DS_Store

venv
.gradle
# Object files
*.o
*.ko
Expand Down
28 changes: 25 additions & 3 deletions bindings/const_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@

template = {
'java': {
'header': "// For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT\npackage capstone;\n\npublic class %s_const {\n",
'header': "// For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT\npackage capstone;\n\nimport static capstone.Capstone.*;\n\npublic class %s_const {\n",
'footer': "}",
'line_format': '\tpublic static final int %s = %s;\n',
'line_format_64': '\tpublic static final long %s = %s;\n',
'out_file': './java/capstone/%s_const.java',
# prefixes for constant filenames of all archs - case sensitive
'arm.h': 'Arm',
'aarch64.h': ['AArch64', 'AARCH64'],
'm68k.h': 'M68k',
'mips.h': 'Mips',
'x86.h': 'X86',
Expand All @@ -29,6 +31,16 @@
'm680x.h': 'M680x',
'evm.h': 'Evm',
'wasm.h': 'Wasm',
'mos65xx.h': 'Mos65xx',
'bpf.h': 'Bpf',
'riscv.h': 'Riscv',
'sh.h': 'Sh',
'tricore.h': ['Tricore', 'TRICORE'],
'alpha.h': ['Alpha', 'ALPHA'],
'hppa.h': 'Hppa',
'loongarch.h': 'Loongarch',
'xtensa.h': 'Xtensa',
'arc.h': 'Arc',
'comment_open': '\t//',
'comment_close': '',
},
Expand Down Expand Up @@ -134,7 +146,6 @@ def gen(lang):
global include, INCL_DIR
print('Generating bindings for', lang)
templ = template[lang]
print('Generating bindings for', lang)
for target in include:
if target not in templ:
print("Warning: No binding found for %s" % target)
Expand All @@ -143,7 +154,9 @@ def gen(lang):
prefixs = []
if isinstance(prefix, list):
prefixs = prefix
prefix = prefix[0].lower()
prefix = prefix[0]
if target == 'python':
prefix = prefix.lower()

outfile = open(templ['out_file'] %(prefix), 'wb') # open as binary prevents windows newlines
outfile.write((templ['header'] % (prefix)).encode("utf-8"))
Expand Down Expand Up @@ -311,6 +324,15 @@ def has_special_arch_prefix(x):
outfile.write((templ['doc_line_format'] %(doc)).encode("utf-8"))
else:
line_format = templ['line_format']
if lang == 'java':
try:
value_int = eval(value)
if value_int > 0x7fffffff:
if '1<<' in value:
value = value.replace('1<<', '1L<<')
line_format = templ['line_format_64']
except Exception:
pass

outfile.write((line_format %(name, value)).encode("utf-8"))

Expand Down
2 changes: 1 addition & 1 deletion bindings/java/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
*.class
tags
*.jar
23 changes: 17 additions & 6 deletions bindings/java/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,25 @@ endif

PYTHON2 ?= python

CAPSTONE_JAVA = Capstone.java Arm_const.java Arm64_const.java Mips_const.java \
CAPSTONE_JAVA = Capstone.java Arm_const.java AArch64_const.java Mips_const.java \
X86_const.java Xcore_const.java Ppc_const.java Sparc_const.java\
Sysz_const.java M680x_const.java \
Arm.java Arm64.java Mips.java X86.java Xcore.java Ppc.java\
Sparc.java Systemz.java M680x.java
Systemz_const.java M680x_const.java Riscv_const.java Sh_const.java \
Bpf_const.java M68k_const.java TMS320C64x_const.java Evm_const.java \
Mos65xx_const.java Wasm_const.java Tricore_const.java Hppa_const.java \
Loongarch_const.java Alpha_const.java Xtensa_const.java \
Arc_const.java \
Arm.java AArch64.java Mips.java X86.java Xcore.java Ppc.java\
Sparc.java Systemz.java M680x.java Riscv.java Sh.java Bpf.java \
Alpha.java Hppa.java Tricore.java Loongarch.java M68k.java \
Evm.java Mos65xx.java Wasm.java TMS320C64x.java Xtensa.java \
Arc.java

all: gen_const capstone tests

capstone: capstone_class
@mkdir -p $(BLDIR)
cd $(OBJDIR) && jar cf $(BLDIR)/capstone.jar capstone/*.class
cp $(BLDIR)/capstone.jar cstest_java/app/libs

capstone_class: jna
ifdef BUILDDIR
Expand All @@ -45,7 +53,7 @@ endif
tests: capstone_class jna
@mkdir -p $(OBJDIR)
javac -d $(OBJDIR) -classpath "$(JNA):$(BLDIR)/capstone.jar" TestBasic.java\
TestArm.java TestArm64.java TestMips.java TestX86.java TestXcore.java\
TestArm.java TestAArch64.java TestMips.java TestX86.java TestXcore.java\
TestPpc.java TestSparc.java TestSystemz.java TestM680x.java

gen_const:
Expand All @@ -62,10 +70,13 @@ ifdef BUILDDIR
rm -rf $(OBJDIR)
endif

TESTS = testbasic arm arm64 m680x mips ppc sparc systemz x86 xcore
TESTS = testbasic arm aarch64 m680x mips ppc sparc systemz x86 xcore
check:
@for t in $(TESTS); do \
echo Check $$t ... ; \
./run.sh $$t > /dev/null && echo OK || echo FAILED; \
done

cstest: capstone
cd cstest_java && ./gradlew run -Djna.library.path=$(shell pwd)/../../build -Djna.debug_load=true --args='--verbosity=info --exclude should_fail_I.yaml --exclude should_fail_II.yaml --exclude should_fail_III.yaml --exclude should_fail_IV.yaml --exclude should_fail_V.yaml --exclude should_fail_VI.yaml'

62 changes: 30 additions & 32 deletions bindings/java/TestArm64.java → bindings/java/TestAArch64.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
// By Nguyen Anh Quynh & Dang Hoang Vu, 2013

import capstone.Capstone;
import capstone.Arm64;
import capstone.AArch64;

import static capstone.Arm64_const.*;
import static capstone.AArch64_const.*;

public class TestArm64 {
public class TestAArch64 {

static byte[] hexString2Byte(String s) {
// from http://stackoverflow.com/questions/140131/convert-a-string-representation-of-a-hex-dump-to-a-byte-array-using-java
Expand Down Expand Up @@ -34,68 +34,66 @@ private static String hex(long i) {
public static void print_ins_detail(Capstone.CsInsn ins) {
System.out.printf("0x%x:\t%s\t%s\n", ins.address, ins.mnemonic, ins.opStr);

Arm64.OpInfo operands = (Arm64.OpInfo) ins.operands;
AArch64.OpInfo operands = (AArch64.OpInfo) ins.operands;

if (operands.op.length != 0) {
System.out.printf("\top_count: %d\n", operands.op.length);
for (int c=0; c<operands.op.length; c++) {
Arm64.Operand i = (Arm64.Operand) operands.op[c];
if (operands.operands.length != 0) {
System.out.printf("\top_count: %d\n", operands.operands.length);
for (int c=0; c<operands.operands.length; c++) {
AArch64.Operand i = (AArch64.Operand) operands.operands[c];
String imm = hex(i.value.imm);
if (i.type == ARM64_OP_REG)
if (i.type == AARCH64_OP_REG)
System.out.printf("\t\toperands[%d].type: REG = %s\n", c, ins.regName(i.value.reg));
if (i.type == ARM64_OP_REG_MRS)
if (i.type == AARCH64_OP_REG_MRS)
System.out.printf("\t\toperands[%d].type: REG_MRS = 0x%x\n", c, i.value.reg);
if (i.type == ARM64_OP_REG_MSR)
if (i.type == AARCH64_OP_REG_MSR)
System.out.printf("\t\toperands[%d].type: REG_MSR = 0x%x\n", c, i.value.reg);
if (i.type == ARM64_OP_PSTATE)
System.out.printf("\t\toperands[%d].type: PSTATE = 0x%x\n", c, i.value.imm);
if (i.type == ARM64_OP_BARRIER)
System.out.printf("\t\toperands[%d].type: BARRIER = 0x%x\n", c, i.value.imm);
// if (i.type == AARCH64_OP_PSTATE)
// System.out.printf("\t\toperands[%d].type: PSTATE = 0x%x\n", c, i.value.imm);
// if (i.type == AARCH64_OP_BARRIER)
// System.out.printf("\t\toperands[%d].type: BARRIER = 0x%x\n", c, i.value.imm);
Comment on lines +50 to +53
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// if (i.type == AARCH64_OP_PSTATE)
// System.out.printf("\t\toperands[%d].type: PSTATE = 0x%x\n", c, i.value.imm);
// if (i.type == AARCH64_OP_BARRIER)
// System.out.printf("\t\toperands[%d].type: BARRIER = 0x%x\n", c, i.value.imm);


if (i.type == ARM64_OP_IMM)
if (i.type == AARCH64_OP_IMM)
System.out.printf("\t\toperands[%d].type: IMM = 0x%x\n", c, i.value.imm);
if (i.type == ARM64_OP_CIMM)
if (i.type == AARCH64_OP_CIMM)
System.out.printf("\t\toperands[%d].type: C-IMM = %d\n", c, i.value.imm);
if (i.type == ARM64_OP_FP)
if (i.type == AARCH64_OP_FP)
System.out.printf("\t\toperands[%d].type: FP = %f\n", c, i.value.fp);
if (i.type == ARM64_OP_MEM) {
if (i.type == AARCH64_OP_MEM) {
System.out.printf("\t\toperands[%d].type: MEM\n",c);
String base = ins.regName(i.value.mem.base);
String index = ins.regName(i.value.mem.index);
if (base != null)
System.out.printf("\t\t\toperands[%d].mem.base: REG = %s\n", c, base);
if (index != null)
System.out.printf("\t\t\toperands[%d].mem.index: REG = %s\n", c, index);
if (i.value.mem.base != AARCH64_REG_INVALID)
System.out.printf("\t\t\toperands[%d].mem.base: REG = %s\n", c, ins.regName(i.value.mem.base));
if (i.value.mem.index != AARCH64_REG_INVALID)
System.out.printf("\t\t\toperands[%d].mem.index: REG = %s\n", c, ins.regName(i.value.mem.index));
if (i.value.mem.disp != 0)
System.out.printf("\t\t\toperands[%d].mem.disp: 0x%x\n", c, i.value.mem.disp);
}
if (i.shift.type != ARM64_SFT_INVALID && i.shift.value > 0)
if (i.shift.type != AARCH64_SFT_INVALID && i.shift.value > 0)
System.out.printf("\t\t\tShift: type = %d, value = %d\n", i.shift.type, i.shift.value);
if (i.ext != ARM64_EXT_INVALID)
if (i.ext != AARCH64_EXT_INVALID)
System.out.printf("\t\t\tExt: %d\n", i.ext);
if (i.vas != ARM64_VAS_INVALID)
if (i.vas != AARCH64LAYOUT_INVALID)
System.out.printf("\t\t\tVector Arrangement Specifier: 0x%x\n", i.vas);
if (i.vector_index != -1)
System.out.printf("\t\t\tVector Index: %d\n", i.vector_index);

}
}

if (operands.writeback)
System.out.println("\tWrite-back: True");
// if (operands.writeback)
// System.out.println("\tWrite-back: True");
Comment on lines +82 to +83
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// if (operands.writeback)
// System.out.println("\tWrite-back: True");


if (operands.updateFlags)
System.out.println("\tUpdate-flags: True");

if (operands.cc != ARM64_CC_AL && operands.cc != ARM64_CC_INVALID)
if (operands.cc != AArch64CC_Invalid)
System.out.printf("\tCode-condition: %d\n", operands.cc);

}

public static void main(String argv[]) {

final TestBasic.platform[] all_tests = {
new TestBasic.platform(Capstone.CS_ARCH_ARM64, Capstone.CS_MODE_ARM, hexString2Byte(ARM64_CODE), "ARM-64"),
new TestBasic.platform(Capstone.CS_ARCH_AARCH64, Capstone.CS_MODE_ARM, hexString2Byte(ARM64_CODE), "ARM-64"),
};

for (int i=0; i<all_tests.length; i++) {
Expand Down
20 changes: 10 additions & 10 deletions bindings/java/TestArm.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ public static void print_ins_detail(Capstone.CsInsn ins) {

Arm.OpInfo operands = (Arm.OpInfo) ins.operands;

if (operands.op.length != 0) {
System.out.printf("\top_count: %d\n", operands.op.length);
for (int c=0; c<operands.op.length; c++) {
Arm.Operand i = (Arm.Operand) operands.op[c];
if (operands.operands.length != 0) {
System.out.printf("\top_count: %d\n", operands.operands.length);
for (int c=0; c<operands.operands.length; c++) {
Arm.Operand i = (Arm.Operand) operands.operands[c];
String imm = hex(i.value.imm);
if (i.type == ARM_OP_SYSREG)
System.out.printf("\t\toperands[%d].type: SYSREG = %d\n", c, i.value.reg);
Expand Down Expand Up @@ -70,24 +70,24 @@ public static void print_ins_detail(Capstone.CsInsn ins) {
System.out.printf("\t\t\toperands[%d].mem.scale: %d\n", c, (i.value.mem.scale));
if (i.value.mem.disp != 0)
System.out.printf("\t\t\toperands[%d].mem.disp: 0x%x\n", c, (i.value.mem.disp));
if (i.value.mem.lshift != 0)
System.out.printf("\t\t\toperands[%d].mem.lshift: 0x%x\n", c, (i.value.mem.lshift));
if (i.value.mem.align != 0)
System.out.printf("\t\t\toperands[%d].mem.align: 0x%x\n", c, (i.value.mem.align));
}
if (i.vector_index > 0)
System.out.printf("\t\t\toperands[%d].vector_index = %d\n", c, (i.vector_index));
if (i.shift.type != ARM_SFT_INVALID && i.shift.value > 0)
System.out.printf("\t\t\tShift: %d = %d\n", i.shift.type, i.shift.value);
if (i.subtracted)
if (i.subtracted != 0)
System.out.printf("\t\t\toperands[%d].subtracted = True\n", c);
}
}
if (operands.writeback)
System.out.println("\tWrite-back: True");
// if (operands.writeback)
// System.out.println("\tWrite-back: True");
Comment on lines +84 to +85
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// if (operands.writeback)
// System.out.println("\tWrite-back: True");


if (operands.updateFlags)
System.out.println("\tUpdate-flags: True");

if (operands.cc != ARM_CC_AL && operands.cc != ARM_CC_INVALID)
if (operands.cc != ARMCC_AL && operands.cc != ARMCC_UNDEF)
System.out.printf("\tCode condition: %d\n", operands.cc);

if (operands.cpsMode > 0)
Expand Down
Loading
Loading