Skip to content
Merged
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
19 changes: 19 additions & 0 deletions capstone-rs/src/arch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,18 @@ macro_rules! arch_info_base {
)
( both_endian: true )
]
[
( riscv, RISCV )
( mode:
RiscV32,
RiscV64,
)
( extra_modes:
RiscVC,
)
( syntax: )
( both_endian: true )
]
[
( sparc, SPARC )
( mode:
Expand Down Expand Up @@ -483,6 +495,13 @@ macro_rules! detail_arch_base {
/// Returns the PPC details, if any
=> arch_name = ppc,
]
[
detail = RiscVDetail,
insn_detail = RiscVInsnDetail<'a>,
op = RiscVOperand,
/// Returns the RISCV details, if any
=> arch_name = riscv,
]
[
detail = SparcDetail,
insn_detail = SparcInsnDetail<'a>,
Expand Down
90 changes: 90 additions & 0 deletions capstone-rs/src/arch/riscv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
//! Contains riscv-specific types

use core::convert::From;
use core::{cmp, fmt, slice};

// XXX todo(tmfink): create rusty versions
pub use capstone_sys::riscv_insn_group as RiscVInsnGroup;
pub use capstone_sys::riscv_insn as RiscVInsn;
pub use capstone_sys::riscv_reg as RiscVReg;
use capstone_sys::{cs_riscv, cs_riscv_op, riscv_op_mem, riscv_op_type};

pub use crate::arch::arch_builder::riscv::*;
use crate::arch::DetailsArchInsn;
use crate::instruction::{RegId, RegIdInt};

/// Contains RISCV-specific details for an instruction
pub struct RiscVInsnDetail<'a>(pub(crate) &'a cs_riscv);

impl_PartialEq_repr_fields!(RiscVInsnDetail<'a> [ 'a ];
operands
);

/// RISCV operand
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum RiscVOperand {
/// Register
Reg(RegId),

/// Immediate
Imm(i64),

/// Memory
Mem(RiscVOpMem),

/// Invalid
Invalid,
}

impl Default for RiscVOperand {
fn default() -> Self {
RiscVOperand::Invalid
}
}

/// RISCV memory operand
#[derive(Debug, Copy, Clone)]
pub struct RiscVOpMem(pub(crate) riscv_op_mem);

impl RiscVOpMem {
/// Base register
pub fn base(&self) -> RegId {
RegId(self.0.base as RegIdInt)
}

/// Disp value
pub fn disp(&self) -> i64 {
self.0.disp
}
}

impl_PartialEq_repr_fields!(RiscVOpMem;
base, disp
);

impl cmp::Eq for RiscVOpMem {}

impl<'a> From<&'a cs_riscv_op> for RiscVOperand {
fn from(insn: &cs_riscv_op) -> RiscVOperand {
match insn.type_ {
riscv_op_type::RISCV_OP_REG => {
RiscVOperand::Reg(RegId(unsafe { insn.__bindgen_anon_1.reg } as RegIdInt))
}
riscv_op_type::RISCV_OP_IMM => RiscVOperand::Imm(unsafe { insn.__bindgen_anon_1.imm }),
riscv_op_type::RISCV_OP_MEM => {
RiscVOperand::Mem(RiscVOpMem(unsafe { insn.__bindgen_anon_1.mem }))
}
riscv_op_type::RISCV_OP_INVALID => RiscVOperand::Invalid,
}
}
}

def_arch_details_struct!(
InsnDetail = RiscVInsnDetail;
Operand = RiscVOperand;
OperandIterator = RiscVOperandIterator;
OperandIteratorLife = RiscVOperandIterator<'a>;
[ pub struct RiscVOperandIterator<'a>(slice::Iter<'a, cs_riscv_op>); ]
cs_arch_op = cs_riscv_op;
cs_arch = cs_riscv;
);
8 changes: 8 additions & 0 deletions capstone-rs/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,8 @@ define_cs_enum_wrapper!(
=> M680X = CS_ARCH_M680X;
/// EVM
=> EVM = CS_ARCH_EVM;
/// RISC-V
=> RISCV = CS_ARCH_RISCV;
);

define_cs_enum_wrapper!(
Expand Down Expand Up @@ -280,6 +282,10 @@ define_cs_enum_wrapper!(
=> M680xCpu12 = CS_MODE_M680X_CPU12;
/// M680X Freescale/NXP HCS08 mode
=> M680xHcs08 = CS_MODE_M680X_HCS08;
/// RISC-V 32-bit mode
=> RiscV32 = CS_MODE_RISCV32;
/// RISC-V 64-bit mode
=> RiscV64 = CS_MODE_RISCV64;
/// Default mode for little-endian
=> Default = CS_MODE_LITTLE_ENDIAN;
);
Expand All @@ -295,6 +301,8 @@ define_cs_enum_wrapper!(
=> V8 = CS_MODE_V8;
/// MicroMips mode. Works in `MIPS` mode.
=> Micro = CS_MODE_MICRO;
/// RISC-V compressed instruction mode
=> RiscVC = CS_MODE_RISCVC;
);

define_cs_enum_wrapper!(
Expand Down
1 change: 1 addition & 0 deletions capstone-rs/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ impl<'a> InsnDetail<'a> {
[M68K, M68kDetail, M68kInsnDetail, m68k]
[MIPS, MipsDetail, MipsInsnDetail, mips]
[PPC, PpcDetail, PpcInsnDetail, ppc]
[RISCV, RiscVDetail, RiscVInsnDetail, riscv]
[SPARC, SparcDetail, SparcInsnDetail, sparc]
[TMS320C64X, Tms320c64xDetail, Tms320c64xInsnDetail, tms320c64x]
[X86, X86Detail, X86InsnDetail, x86]
Expand Down
111 changes: 111 additions & 0 deletions capstone-rs/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3053,6 +3053,117 @@ fn test_arch_xcore_detail() {
);
}

#[test]
fn test_arch_riscv() {
test_arch_mode_endian_insns(
&mut Capstone::new()
.riscv()
.mode(riscv::ArchMode::RiscV64)
.extra_mode([riscv::ArchExtraMode::RiscVC].iter().map(|x| *x))
.build()
.unwrap(),
Arch::RISCV,
Mode::RiscV64,
None,
&[ExtraMode::RiscVC],
&[
("addi", b"\x93\x00\x31\x00"),
("add", b"\xb3\x00\x31\x00"),
("ld", b"\x03\xb2\x82\x00"),
("c.ebreak", b"\x02\x90"),
("c.addi", b"\x05\x04"),
("c.add", b"\x2a\x94"),
("c.ld", b"\x0c\x66"),
],
);
}

#[test]
fn test_arch_riscv_detail() {
use crate::arch::riscv::RiscVOperand::*;
use crate::arch::riscv::RiscVReg::*;
use crate::arch::riscv::*;
use capstone_sys::riscv_op_mem;

test_arch_mode_endian_insns_detail(
&mut Capstone::new()
.riscv()
.mode(riscv::ArchMode::RiscV64)
.extra_mode([riscv::ArchExtraMode::RiscVC].iter().map(|x| *x))
.build()
.unwrap(),
Arch::RISCV,
Mode::RiscV64,
None,
&[ExtraMode::RiscVC],
&[
// addi x1, x2, 3
DII::new(
"addi",
b"\x93\x00\x31\x00",
&[
Reg(RegId(RISCV_REG_X1 as RegIdInt)),
Reg(RegId(RISCV_REG_X2 as RegIdInt)),
Imm(3),
],
),
// add x1, x2, x3
DII::new(
"add",
b"\xb3\x00\x31\x00",
&[
Reg(RegId(RISCV_REG_X1 as RegIdInt)),
Reg(RegId(RISCV_REG_X2 as RegIdInt)),
Reg(RegId(RISCV_REG_X3 as RegIdInt)),
],
),
// ld x4, 8(x5)
DII::new(
"ld",
b"\x03\xb2\x82\x00",
&[
Reg(RegId(RISCV_REG_X4 as RegIdInt)),
Mem(RiscVOpMem(riscv_op_mem {
base: RISCV_REG_X5,
disp: 8,
})),
],
),
// c.ebreak
DII::new("c.ebreak", b"\x02\x90", &[]),
// c.addi x8, 1
DII::new(
"c.addi",
b"\x05\x04",
&[
Reg(RegId(RISCV_REG_X8 as RegIdInt)),
Imm(1),
],
),
// c.add x8, x10
DII::new(
"c.add",
b"\x2a\x94",
&[
Reg(RegId(RISCV_REG_X8 as RegIdInt)),
Reg(RegId(RISCV_REG_X10 as RegIdInt)),
],
),
// c.ld x11, 8(x12)
DII::new(
"c.ld",
b"\x0c\x66",
&[
// Upstream bug? Doesn't seem to use Mem type.
Reg(RegId(RISCV_REG_X11 as RegIdInt)),
Imm(8),
Reg(RegId(RISCV_REG_X12 as RegIdInt)),
],
),
],
);
}

#[test]
fn test_insn_size_and_alignment() {
use capstone_sys::cs_insn;
Expand Down
1 change: 1 addition & 0 deletions capstone-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ fn build_capstone_cc() {
.define("CAPSTONE_HAS_M68K", None)
.define("CAPSTONE_HAS_MIPS", None)
.define("CAPSTONE_HAS_POWERPC", None)
.define("CAPSTONE_HAS_RISCV", None)
.define("CAPSTONE_HAS_SPARC", None)
.define("CAPSTONE_HAS_SYSZ", None)
.define("CAPSTONE_HAS_TMS320C64X", None)
Expand Down
8 changes: 8 additions & 0 deletions capstone-sys/capstone/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ 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_DEBUG "Whether to enable extra debug assertions" OFF)
option(CAPSTONE_INSTALL "Generate install target" OFF)

set(SUPPORTED_ARCHITECTURES ARM ARM64 M68K MIPS PPC SPARC SYSZ XCORE X86 TMS320C64X M680X EVM MOS65XX WASM BPF RISCV)
set(SUPPORTED_ARCHITECTURE_LABELS ARM ARM64 M68K MIPS PowerPC Sparc SystemZ XCore x86 TMS320C64x M680x EVM MOS65XX WASM BPF RISCV)
Expand Down Expand Up @@ -655,7 +656,9 @@ source_group("Include\\RISCV" FILES ${HEADERS_RISCV})
include("GNUInstallDirs")

## installation
if (CAPSTONE_INSTALL)
install(FILES ${HEADERS_COMMON} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/capstone)
endif ()
configure_file(capstone.pc.in ${CMAKE_BINARY_DIR}/capstone.pc @ONLY)

include(CMakePackageConfigHelpers)
Expand All @@ -670,6 +673,8 @@ write_basic_package_version_file(
VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}
COMPATIBILITY SameMajorVersion
)

if (CAPSTONE_INSTALL)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/capstone-config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/capstone-config-version.cmake"
Expand Down Expand Up @@ -697,12 +702,15 @@ endif ()
install(EXPORT capstone-targets
NAMESPACE capstone::
DESTINATION ${CAPSTONE_CMAKE_CONFIG_INSTALL_DIR})
endif ()

if (CAPSTONE_BUILD_SHARED AND CAPSTONE_BUILD_CSTOOL)
FILE(GLOB CSTOOL_SRC cstool/*.c)
add_executable(cstool ${CSTOOL_SRC})
target_link_libraries(cstool ${default-target})

if (CAPSTONE_INSTALL)
install(TARGETS cstool DESTINATION ${CMAKE_INSTALL_BINDIR})
install(FILES ${CMAKE_BINARY_DIR}/capstone.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
endif ()
endif ()
1 change: 1 addition & 0 deletions capstone-sys/capstone/MCInst.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion capstone-sys/capstone/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Capstone offers some unparalleled features:
- Provide semantics of the disassembled instruction, such as list of implicit
registers read & written.

- Implemented in pure C language, with lightweight bindings for D, Clojure, F#,
- Implemented in pure C language, with lightweight bindings for Swift, D, Clojure, F#,
Common Lisp, Visual Basic, PHP, PowerShell, Emacs, Haskell, Perl, Python,
Ruby, C#, NodeJS, Java, GO, C++, OCaml, Lua, Rust, Delphi, Free Pascal & Vala
ready either in main code, or provided externally by the community).
Expand Down
11 changes: 0 additions & 11 deletions capstone-sys/capstone/arch/M680X/M680XDisassembler.c
Original file line number Diff line number Diff line change
Expand Up @@ -2130,11 +2130,6 @@ static const cpu_tables g_cpu_tables[] = {
},
};

static const char * const 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)
Expand Down Expand Up @@ -2264,12 +2259,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));

Expand Down
12 changes: 9 additions & 3 deletions capstone-sys/capstone/arch/M68K/M68KDisassembler.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -2594,7 +2600,7 @@ static void d68010_movec(m68k_info *info)
case 0x807: reg = M68K_REG_SRP; break;
}

if (BIT_1(info->ir)) {
if (BIT_0(info->ir)) {
op0->reg = (BIT_F(extension) ? M68K_REG_A0 : M68K_REG_D0) + ((extension >> 12) & 7);
op1->reg = reg;
} else {
Expand Down
Loading