From 622fe09217bb61cb15b1bfb9502e519614b9448f Mon Sep 17 00:00:00 2001 From: Trey Keown Date: Mon, 21 Jan 2019 04:03:23 -0500 Subject: [PATCH 01/12] Fix ADRP instruction encoding (#396) * Fix ADRP instruction encoding * Trigger checks on PR again, it failed for some reason unrelated to my code * Add correct offset checks back in --- llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp | 5 +++-- .../lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index 30182862..aef22a45 100644 --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -1133,10 +1133,11 @@ class AArch64Operand : public MCParsedAsmOperand { return false; if (const MCConstantExpr *CE = dyn_cast(Imm.Val)) { - int64_t Val = CE->getValue() - Ctx.getBaseAddress(); + int64_t Val = CE->getValue(); + int64_t Offset = Val - Ctx.getBaseAddress(); int64_t Min = - (4096 * (1LL << (21 - 1))); int64_t Max = 4096 * ((1LL << (21 - 1)) - 1); - return (Val % 4096) == 0 && Val >= Min && Val <= Max; + return (Val % 4096) == 0 && Offset >= Min && Offset <= Max; } return true; diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp index f7f17eeb..c07084e7 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp @@ -219,7 +219,7 @@ AArch64MCCodeEmitter::getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx, // If the destination is an immediate, we have nothing to do. if (MO.isImm()) - return (MO.getImm() * 4096 - MI.getAddress()) / 4096; + return MO.getImm() - (MI.getAddress() >> 12); assert(MO.isExpr() && "Unexpected target type!"); const MCExpr *Expr = MO.getExpr(); From d49b6fa4013efb919d434bfd439311d6cb67a0f7 Mon Sep 17 00:00:00 2001 From: Catena cyber <35799796+catenacyber@users.noreply.github.com> Date: Fri, 8 Feb 2019 03:26:25 +0100 Subject: [PATCH 02/12] Sets a default radix (#382) * Sets a default radix * Default radix is 16 --- llvm/keystone/ks.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/keystone/ks.cpp b/llvm/keystone/ks.cpp index bfb0f6a8..453df774 100644 --- a/llvm/keystone/ks.cpp +++ b/llvm/keystone/ks.cpp @@ -522,6 +522,7 @@ ks_err ks_close(ks_engine *ks) KEYSTONE_EXPORT ks_err ks_option(ks_engine *ks, ks_opt_type type, size_t value) { + ks->MAI->setRadix(16); switch(type) { case KS_OPT_SYNTAX: if (ks->arch != KS_ARCH_X86) From 06afb493e09cb7591fedf17cc5b06f9a865b385c Mon Sep 17 00:00:00 2001 From: Ed Larson Date: Mon, 15 Jul 2019 16:50:20 -0400 Subject: [PATCH 03/12] Remove bounds check on ppc branch instructions target address (fix issue 423) --- .../Target/PowerPC/AsmParser/PPCAsmParser.cpp | 24 +++-------- suite/regress/ppc_branch_addressing.py | 43 +++++++++++++++++++ 2 files changed, 49 insertions(+), 18 deletions(-) create mode 100644 suite/regress/ppc_branch_addressing.py diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp index e3b18853..008efcd4 100644 --- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -503,25 +503,13 @@ struct PPCOperand : public MCParsedAsmOperand { } bool isTLSReg() const { return Kind == TLSRegister; } bool isDirectBr() const { - if (Kind == Expression) - return true; - if (Kind != Immediate) - return false; - // Operand must be 64-bit aligned, signed 27-bit immediate. - if ((getImm() & 3) != 0) - return false; - if (isInt<26>(getImm())) - return true; - if (!IsPPC64) { - // In 32-bit mode, large 32-bit quantities wrap around. - if (isUInt<32>(getImm()) && isInt<26>(static_cast(getImm()))) - return true; - } - return false; + return (Kind == Expression) + ||((Kind == Immediate) && ((getImm() & 3) == 0)); + } + bool isCondBr() const { + return (Kind == Expression) + ||((Kind == Immediate) && ((getImm() & 3) == 0)); } - bool isCondBr() const { return Kind == Expression || - (Kind == Immediate && isInt<16>(getImm()) && - (getImm() & 3) == 0); } bool isRegNumber() const { return Kind == Immediate && isUInt<5>(getImm()); } bool isVSRegNumber() const { return Kind == Immediate && isUInt<6>(getImm()); } bool isCCRegNumber() const { return (Kind == Expression diff --git a/suite/regress/ppc_branch_addressing.py b/suite/regress/ppc_branch_addressing.py new file mode 100644 index 00000000..84cebcbb --- /dev/null +++ b/suite/regress/ppc_branch_addressing.py @@ -0,0 +1,43 @@ +from keystone import * +import regress + +# Github issue: #423 +# Author: Edward Larson + +class TestBranchRelativeAddressing(regress.RegressTest): + def kstest(self, arch, mode, code, expect, syntax = 0, address = 0): + ks = Ks(arch, mode) + if syntax != 0: + ks.syntax = syntax + encoding, count = ks.asm(code, address) + self.assertEqual(expect, encoding) + + def runTest(self): + # 0x1fffffc is largest positive branch offset in PPC, 0x2000000 is largest negative branch offset + self.kstest(KS_ARCH_PPC, KS_MODE_PPC32 | KS_MODE_BIG_ENDIAN, b"b 0x1fffffc", [0x49, 0xff, 0xff, 0xfc], address=0x0) + self.kstest(KS_ARCH_PPC, KS_MODE_PPC32 | KS_MODE_BIG_ENDIAN, b"b 0x2000000", [0x49, 0xff, 0xff, 0xfc], address=0x4) + self.kstest(KS_ARCH_PPC, KS_MODE_PPC32 | KS_MODE_BIG_ENDIAN, b"b 0x0", [0x4a, 0x00, 0x00, 0x00], address=0x2000000) + # beyond max positive range, branch will wrap around to negative + self.kstest(KS_ARCH_PPC, KS_MODE_PPC32 | KS_MODE_BIG_ENDIAN, b"b 0x2000000", [0x4a, 0, 0, 0], address=0x0) + # beyond max negative range, branch will wrap ardound to positive + self.kstest(KS_ARCH_PPC, KS_MODE_PPC32 | KS_MODE_BIG_ENDIAN, b"b 0x0", [0x49, 0xff, 0xff, 0xfc], address=0x2000004) + + +class TestBranchAbsoluteAddressing(regress.RegressTest): + def kstest(self, arch, mode, code, expect, syntax = 0, address = 0): + ks = Ks(arch, mode) + if syntax != 0: + ks.syntax = syntax + encoding, count = ks.asm(code, address) + self.assertEqual(expect, encoding) + + def runTest(self): + # 0x1fffffc is largest absolute offset in PPC + self.kstest(KS_ARCH_PPC, KS_MODE_PPC32 | KS_MODE_BIG_ENDIAN, b"ba 0x1fffffc", [0x49, 0xff, 0xff, 0xfe], address=0x0) + self.kstest(KS_ARCH_PPC, KS_MODE_PPC32 | KS_MODE_BIG_ENDIAN, b"ba 0x1fffffc", [0x49, 0xff, 0xff, 0xfe], address=0x4) + # beyond max positive range, branch will wrap around to negative + self.kstest(KS_ARCH_PPC, KS_MODE_PPC32 | KS_MODE_BIG_ENDIAN, b"ba 0x2000000", [0x4a, 0, 0, 2], address=0x0) + + +if __name__ == '__main__': + regress.main() \ No newline at end of file From 06425a32f3773134ab627a8598f45198f9749cdb Mon Sep 17 00:00:00 2001 From: Ed Larson Date: Fri, 26 Jul 2019 15:35:26 -0400 Subject: [PATCH 04/12] Fix vm address reset in aliased PPC instructions --- .../Target/PowerPC/AsmParser/PPCAsmParser.cpp | 3 + suite/regress/ppc_address_consistency.py | 58 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 suite/regress/ppc_address_consistency.py diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp index 008efcd4..0dc20a32 100644 --- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -816,6 +816,7 @@ addNegOperand(MCInst &Inst, MCOperand &Op, MCContext &Ctx) { void PPCAsmParser::ProcessInstruction(MCInst &Inst, const OperandVector &Operands) { int Opcode = Inst.getOpcode(); + uint64_t address = Inst.getAddress(); switch (Opcode) { case PPC::DCBTx: case PPC::DCBTT: @@ -1181,6 +1182,8 @@ void PPCAsmParser::ProcessInstruction(MCInst &Inst, break; } } + // if original instruction was overwritten, need to preserve its address + Inst.setAddress(address); } bool PPCAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, diff --git a/suite/regress/ppc_address_consistency.py b/suite/regress/ppc_address_consistency.py new file mode 100644 index 00000000..d371aa58 --- /dev/null +++ b/suite/regress/ppc_address_consistency.py @@ -0,0 +1,58 @@ +from keystone import * +import regress + +# Author: Edward Larson + +class TestAddressConsistency(regress.RegressTest): + def kstest_address_consistency(self, inst_assembly): + ks = Ks(KS_ARCH_PPC, KS_MODE_32 | KS_MODE_BIG_ENDIAN) + + + # relative branch to its own address should always be encoded with branch target 0 + start_address = 0x1000 + branch_assembly = "b 0x1004" + branch_mc = [0x48, 0x00, 0x00, 0x00] + + code = inst_assembly + "; " + branch_assembly + + encoding, count = ks.asm(code, start_address) + + last_instruction_mc = encoding[-4:] + + self.assertEqual(branch_mc, last_instruction_mc) + + def runTest(self): + # un-aliased instructions + self.kstest_address_consistency("nop") + self.kstest_address_consistency("add 0, 0, 0") + + # aliased instructions + self.kstest_address_consistency("dcbtt 0, 0") + self.kstest_address_consistency("dcbtct 0, 0, 0") + self.kstest_address_consistency("dcbtstct 0, 0, 0") + self.kstest_address_consistency("la 1, 0, 1") + self.kstest_address_consistency("subi 0, 0, 0") + self.kstest_address_consistency("subis 0, 0, 0") + self.kstest_address_consistency("subic 0, 0, 0") + self.kstest_address_consistency("subic. 0, 0, 0") + self.kstest_address_consistency("extlwi 0, 0, 0, 0") + self.kstest_address_consistency("extrwi 0, 0, 0, 0") + self.kstest_address_consistency("inslwi 0, 0, 0, 0") + self.kstest_address_consistency("insrwi 0, 0, 0, 0") + self.kstest_address_consistency("rotrwi 0, 0, 0") + self.kstest_address_consistency("slwi 0, 0, 0") + self.kstest_address_consistency("srwi 0, 0, 0") + self.kstest_address_consistency("clrrwi 0, 0, 0") + self.kstest_address_consistency("clrlslwi 0, 0, 0, 0") + self.kstest_address_consistency("extldi 0, 0, 0, 0") + self.kstest_address_consistency("extrdi 0, 0, 0, 0") + self.kstest_address_consistency("insrdi 0, 0, 0, 0") + self.kstest_address_consistency("rotrdi 0, 0, 0") + self.kstest_address_consistency("sldi 0, 0, 0") + self.kstest_address_consistency("srdi 0, 0, 0") + self.kstest_address_consistency("clrrdi 0, 0, 0") + self.kstest_address_consistency("clrlsldi 0, 0, 0, 0") + self.kstest_address_consistency("rlwinm 0, 0, 0, 1") + self.kstest_address_consistency("rlwimi 0, 0, 0, 1") + self.kstest_address_consistency("rlwnm 0, 0, 0, 1") + self.kstest_address_consistency("mftb 0, 0") From 13b13d99dfc4283fce80b29fd07a39eef3f33c3c Mon Sep 17 00:00:00 2001 From: Jinmo Date: Fri, 2 Aug 2019 22:41:00 +0900 Subject: [PATCH 05/12] add suite/ directory for suite/fuzz, fix python build (#414) --- bindings/python/setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bindings/python/setup.py b/bindings/python/setup.py index cea175c8..a52f1f65 100755 --- a/bindings/python/setup.py +++ b/bindings/python/setup.py @@ -49,6 +49,7 @@ def copy_sources(): dir_util.copy_tree("../../llvm", "src/llvm/") dir_util.copy_tree("../../include", "src/include/") + dir_util.copy_tree("../../suite", "src/suite") src.extend(glob.glob("../../*.h")) src.extend(glob.glob("../../*.cpp")) From ffe054aaa95b586ca4bdb1e1e5ccaddc5c22e997 Mon Sep 17 00:00:00 2001 From: Boris-Chengbiao Zhou Date: Fri, 2 Aug 2019 15:42:21 +0200 Subject: [PATCH 06/12] Various improvements to the Rust bindings (#401) * Fix Rust bindings * Various small improvements for the Rust bindings * Remove unused dependencies * Use the cmake crate to compile keystone * Add Windows support to Rust bindings * Cleanup doc a bit * Fix symlink path * Link to C++ standard library * Build all keystone targets --- bindings/rust/Cargo.toml | 10 ++-- bindings/rust/Makefile | 9 ++- bindings/rust/README.md | 1 + bindings/rust/keystone-sys/Cargo.toml | 12 ++-- bindings/rust/keystone-sys/build.rs | 82 +++++++++++---------------- bindings/rust/keystone-sys/src/lib.rs | 11 ++-- bindings/rust/src/lib.rs | 12 ++-- 7 files changed, 60 insertions(+), 77 deletions(-) diff --git a/bindings/rust/Cargo.toml b/bindings/rust/Cargo.toml index b41e5988..b612c6ca 100644 --- a/bindings/rust/Cargo.toml +++ b/bindings/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "keystone" -version = "0.9.1" +version = "0.10.0" authors = [ "Remco Verhoef ", "Tasuku SUENAGA a.k.a. gunyarakun " @@ -10,17 +10,17 @@ license = "GPL-2.0" readme = "README.md" repository = "https://github.com/keystone-engine/keystone" include = [ - "src/*", "tests/*", "Cargo.toml", "COPYING", "README.md", - "keystone-sys/*" + "src/*", "tests/*", "Cargo.toml", "COPYING", "README.md" ] [dependencies] -bitflags = "1.0" libc = "0.2" -keystone-sys = { path = "keystone-sys", version = "0.9.1" } +keystone-sys = { path = "keystone-sys", version = "0.10" } [features] default = [] use_system_keystone = ["keystone-sys/use_system_keystone"] build_keystone_cmake = ["keystone-sys/build_keystone_cmake"] + +[workspace] diff --git a/bindings/rust/Makefile b/bindings/rust/Makefile index 7a3f1690..05a3a388 100644 --- a/bindings/rust/Makefile +++ b/bindings/rust/Makefile @@ -9,15 +9,18 @@ package: keystone-sys/keystone cd keystone-sys && cargo package -vv cargo package -vv +# For packaging we need to embed the keystone source in the crate keystone-sys/keystone: rsync -a ../.. keystone-sys/keystone --exclude bindings --filter ":- ../../.gitignore" clean: - rm -rf target/ keystone-sys/target/ keystone-sys/keystone/ + rm -rf keystone-sys/keystone/ + cargo clean check: - cargo test +# Make sure to only use one test thread as keystone isn't thread-safe + cargo test -- --test-threads=1 gen_const: - cd .. && python const_generator.py rust + cd .. && python2 const_generator.py rust cargo fmt diff --git a/bindings/rust/README.md b/bindings/rust/README.md index 32cb7a0e..2a608ea4 100644 --- a/bindings/rust/README.md +++ b/bindings/rust/README.md @@ -39,6 +39,7 @@ If you want to use keystone already installed in the system, specify `use_system ``` [dependencies.keystone] version = "0.10.0" +default-features = false features = ["use_system_keystone"] ``` diff --git a/bindings/rust/keystone-sys/Cargo.toml b/bindings/rust/keystone-sys/Cargo.toml index f791327c..adff79f9 100644 --- a/bindings/rust/keystone-sys/Cargo.toml +++ b/bindings/rust/keystone-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "keystone-sys" -version = "0.9.0" +version = "0.10.0" authors = [ "Remco Verhoef ", "Tasuku SUENAGA a.k.a. gunyarakun " @@ -10,21 +10,17 @@ repository = "https://github.com/keystone-engine/keystone" documentation = "https://docs.rs/keystone/" license = "GPL-2.0" build = "build.rs" -exclude = [ - "keystone/build/**" -] [build-dependencies] -build-helper = "0.1" -os_type = "2.0" pkg-config = { optional = true, version = "0.3" } +cmake = { optional = true, version = "0.1" } [dependencies] bitflags = "1.0" libc = "0.2" [features] -default = [] +default = ["build_keystone_cmake"] use_system_keystone = ["pkg-config"] -build_keystone_cmake = [] +build_keystone_cmake = ["cmake"] diff --git a/bindings/rust/keystone-sys/build.rs b/bindings/rust/keystone-sys/build.rs index 2f698ab7..599fc057 100644 --- a/bindings/rust/keystone-sys/build.rs +++ b/bindings/rust/keystone-sys/build.rs @@ -1,42 +1,45 @@ +#[cfg(feature = "build_keystone_cmake")] +extern crate cmake; #[cfg(feature = "use_system_keystone")] extern crate pkg_config; -use std::env; -use std::path::PathBuf; -use std::process::Command; +#[cfg(all(not(windows), feature = "build_keystone_cmake"))] +use std::os::unix::fs::symlink; +#[cfg(all(windows, feature = "build_keystone_cmake"))] +use std::os::windows::fs::symlink_dir as symlink; -fn build_with_cmake() { - let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); - let cmake_dir = PathBuf::from("keystone"); - let build_dir = cmake_dir.join("build"); +#[cfg(feature = "build_keystone_cmake")] +use std::path::Path; - if !cmake_dir.exists() { - run(Command::new("ln").arg("-s").arg("../../..").arg("keystone")); +#[cfg(feature = "build_keystone_cmake")] +fn build_with_cmake() { + if !Path::new("keystone").exists() { + // This only happens when using the crate via a `git` reference as the + // published version already embeds keystone's source. + let pwd = std::env::current_dir().unwrap(); + let keystone_dir = pwd.ancestors().skip(3).next().unwrap(); + symlink(keystone_dir, "keystone").expect("failed to symlink keystone"); } - run(Command::new("mkdir") - .current_dir(&cmake_dir) - .arg("-p") - .arg("build")); - - run(Command::new("../make-share.sh").current_dir(&build_dir)); + let dest = cmake::Config::new("keystone") + .define("BUILD_LIBS_ONLY", "1") + .define("BUILD_SHARED_LIBS", "OFF") + .define("LLVM_TARGETS_TO_BUILD", "all") + // Prevent python from leaving behind `.pyc` files which break `cargo package` + .env("PYTHONDONTWRITEBYTECODE", "1") + .build(); - run(Command::new("cmake").current_dir(&build_dir).args(&[ - &format!("-DCMAKE_INSTALL_PREFIX={}", out_dir.display()), - "-DCMAKE_BUILD_TYPE=Release", - "-DBUILD_LIBS_ONLY=1", - "-DCMAKE_OSX_ARCHITECTURES=", - "-DBUILD_SHARED_LIBS=ON", - "-DLLVM_TARGET_ARCH=host", - "-G", - "Unix Makefiles", - "..", - ])); - - run(Command::new("make").current_dir(&build_dir).arg("install")); - - println!("cargo:rustc-link-search=native={}/lib", out_dir.display()); + println!("cargo:rustc-link-search=native={}/lib", dest.display()); println!("cargo:rustc-link-lib=keystone"); + + let target = std::env::var("TARGET").unwrap(); + if target.contains("apple") { + println!("cargo:rustc-link-lib=dylib=c++"); + } else if target.contains("linux") { + println!("cargo:rustc-link-lib=dylib=stdc++"); + } else if target.contains("windows") { + println!("cargo:rustc-link-lib=dylib=shell32"); + } } fn main() { @@ -44,24 +47,7 @@ fn main() { #[cfg(feature = "use_system_keystone")] pkg_config::find_library("keystone").expect("Could not find system keystone"); } else { + #[cfg(feature = "build_keystone_cmake")] build_with_cmake(); } } - -fn run(cmd: &mut Command) { - println!("run: {:?}", cmd); - let status = match cmd.status() { - Ok(s) => s, - Err(ref e) => fail(&format!("failed to execute command: {}", e)), - }; - if !status.success() { - fail(&format!( - "command did not execute successfully, got: {}", - status - )); - } -} - -fn fail(s: &str) -> ! { - panic!("\n{}\n\nbuild script failed, must exit now", s); -} diff --git a/bindings/rust/keystone-sys/src/lib.rs b/bindings/rust/keystone-sys/src/lib.rs index c063c48a..fa8337fc 100644 --- a/bindings/rust/keystone-sys/src/lib.rs +++ b/bindings/rust/keystone-sys/src/lib.rs @@ -9,17 +9,16 @@ extern crate libc; pub mod keystone_const; -use std::fmt; +use keystone_const::{Arch, Error, Mode, OptionType, OptionValue}; use std::ffi::CStr; +use std::fmt; use std::os::raw::c_char; -use keystone_const::{Arch, Error, Mode, OptionType, OptionValue}; #[allow(non_camel_case_types)] pub type ks_handle = libc::size_t; -#[link(name = "keystone")] extern "C" { - pub fn ks_version(major: *const u32, minor: *const u32) -> u32; + pub fn ks_version(major: *mut u32, minor: *mut u32) -> u32; pub fn ks_arch_supported(arch: Arch) -> bool; pub fn ks_open(arch: Arch, mode: Mode, engine: *mut ks_handle) -> Error; pub fn ks_asm( @@ -38,8 +37,8 @@ extern "C" { } impl Error { - pub fn msg(&self) -> String { - error_msg(*self) + pub fn msg(self) -> String { + error_msg(self) } } diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index 5bcd5bfd..29528808 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -1,6 +1,6 @@ -//! Keystone Assembler Engine (www.keystone-engine.org) */ -//! By Nguyen Anh Quynh , 2016 */ -//! Rust bindings by Remco Verhoef , 2016 */ +//! Keystone Assembler Engine (www.keystone-engine.org) \ +//! By Nguyen Anh Quynh , 2016 \ +//! Rust bindings by Remco Verhoef , 2016 //! //! ```rust //! extern crate keystone; @@ -16,12 +16,10 @@ //! } //! ``` -#![doc(html_root_url = "https://keystone/doc/here/v1")] - extern crate keystone_sys as ffi; extern crate libc; -use std::ffi::CString; +use std::ffi::{CStr, CString}; use std::fmt; pub use ffi::keystone_const::*; @@ -66,7 +64,7 @@ pub fn arch_supported(arch: Arch) -> bool { pub fn error_msg(error: Error) -> String { unsafe { - CStr::from_ptr(ffi::ks_strerror(error.bits())) + CStr::from_ptr(ffi::ks_strerror(error)) .to_string_lossy() .into_owned() } From 34fcbe400daf382cf75f253d2d75d4180ef8c2f8 Mon Sep 17 00:00:00 2001 From: Banny Date: Fri, 2 Aug 2019 21:43:11 +0800 Subject: [PATCH 07/12] Bug fix (#408) Bug fix for win32 jna access --- .../java/keystone/natives/DirectMappingKeystoneNative.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/java/src/main/java/keystone/natives/DirectMappingKeystoneNative.java b/bindings/java/src/main/java/keystone/natives/DirectMappingKeystoneNative.java index 5059ff1d..9083a121 100644 --- a/bindings/java/src/main/java/keystone/natives/DirectMappingKeystoneNative.java +++ b/bindings/java/src/main/java/keystone/natives/DirectMappingKeystoneNative.java @@ -81,7 +81,7 @@ private DirectMappingKeystoneNative() { * @param numberOfStatements number of statements successfully processed * @return 0 on success, or -1 on failure. */ - public static native int ks_asm(Pointer engine, String assembly, int address, PointerByReference machineCodeBuffer, + public static native int ks_asm(Pointer engine, String assembly, long address, PointerByReference machineCodeBuffer, IntByReference machineCodeSize, IntByReference numberOfStatements); /** @@ -176,4 +176,4 @@ public static native int ks_asm(Pointer engine, String assembly, int address, Po * @return An hexadecimal number as (major << 8 | minor), which encodes both major & minor versions. */ public static native int ks_version(IntByReference major, IntByReference minor); -} \ No newline at end of file +} From c4de98f71f05f356817f5e91fee0d509c7b0b440 Mon Sep 17 00:00:00 2001 From: brendabrandy Date: Fri, 2 Aug 2019 09:45:03 -0400 Subject: [PATCH 08/12] Updated AsmParser deconstructor to restore saved diagnostic handlers back to srcmgr (#419) --- llvm/lib/MC/MCParser/AsmParser.cpp | 4 ++++ suite/test_diag_printer.py | 22 ++++++++++++++++++++++ suite/test_diag_printer.sh | 13 +++++++++++++ 3 files changed, 39 insertions(+) create mode 100755 suite/test_diag_printer.py create mode 100755 suite/test_diag_printer.sh diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index 3446db06..5f4a3115 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -581,6 +581,10 @@ AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, AsmParser::~AsmParser() { assert((HadError || ActiveMacros.empty()) && "Unexpected active macro instantiation!"); + + // Restore the saved diagnostics handler and context for use during + // finalization + SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext); } void AsmParser::printMacroInstantiations() { diff --git a/suite/test_diag_printer.py b/suite/test_diag_printer.py new file mode 100755 index 00000000..7ce4443f --- /dev/null +++ b/suite/test_diag_printer.py @@ -0,0 +1,22 @@ +import binascii + +from keystone import Ks, KS_ARCH_ARM, KS_MODE_ARM + +ks = Ks(KS_ARCH_ARM, KS_MODE_ARM) + +assembly_text = \ + """ + sub sp, sp, #8 + push {sp, lr} + bl #0xc6ab8 + ldr lr, [sp, #4] + add sp, sp, #8 + pop {r2, r3} + bx lr + """ + +for i in range(100): + output = ks.asm(assembly_text, 0x902c4, as_bytes=True) + # print("{}: {}: {}".format(i, assembly_text, output)) + output_2 = ks.asm("b #0", 0x4, as_bytes=True) + # print("{}: {}: {}".format(i, "b #0", output_2)) diff --git a/suite/test_diag_printer.sh b/suite/test_diag_printer.sh new file mode 100755 index 00000000..c916d49f --- /dev/null +++ b/suite/test_diag_printer.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +for i in $(seq 1 100) +do + python test_diag_printer.py + + if [ $? -ne 0 ] + then + echo "Diagnostic Handler test failed" + exit + fi +done +echo "Diagnostic Handler test pass" From c74ee9d204707c54c330f86d101a8324e3bbe0c7 Mon Sep 17 00:00:00 2001 From: Ed Larson Date: Fri, 26 Jul 2019 15:35:26 -0400 Subject: [PATCH 09/12] Fix vm address reset in aliased PPC instructions (cherry picked from commit 06425a32f3773134ab627a8598f45198f9749cdb) --- .../Target/PowerPC/AsmParser/PPCAsmParser.cpp | 3 + suite/regress/ppc_address_consistency.py | 58 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 suite/regress/ppc_address_consistency.py diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp index e3b18853..ea73dbf8 100644 --- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -828,6 +828,7 @@ addNegOperand(MCInst &Inst, MCOperand &Op, MCContext &Ctx) { void PPCAsmParser::ProcessInstruction(MCInst &Inst, const OperandVector &Operands) { int Opcode = Inst.getOpcode(); + uint64_t address = Inst.getAddress(); switch (Opcode) { case PPC::DCBTx: case PPC::DCBTT: @@ -1193,6 +1194,8 @@ void PPCAsmParser::ProcessInstruction(MCInst &Inst, break; } } + // if original instruction was overwritten, need to preserve its address + Inst.setAddress(address); } bool PPCAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, diff --git a/suite/regress/ppc_address_consistency.py b/suite/regress/ppc_address_consistency.py new file mode 100644 index 00000000..d371aa58 --- /dev/null +++ b/suite/regress/ppc_address_consistency.py @@ -0,0 +1,58 @@ +from keystone import * +import regress + +# Author: Edward Larson + +class TestAddressConsistency(regress.RegressTest): + def kstest_address_consistency(self, inst_assembly): + ks = Ks(KS_ARCH_PPC, KS_MODE_32 | KS_MODE_BIG_ENDIAN) + + + # relative branch to its own address should always be encoded with branch target 0 + start_address = 0x1000 + branch_assembly = "b 0x1004" + branch_mc = [0x48, 0x00, 0x00, 0x00] + + code = inst_assembly + "; " + branch_assembly + + encoding, count = ks.asm(code, start_address) + + last_instruction_mc = encoding[-4:] + + self.assertEqual(branch_mc, last_instruction_mc) + + def runTest(self): + # un-aliased instructions + self.kstest_address_consistency("nop") + self.kstest_address_consistency("add 0, 0, 0") + + # aliased instructions + self.kstest_address_consistency("dcbtt 0, 0") + self.kstest_address_consistency("dcbtct 0, 0, 0") + self.kstest_address_consistency("dcbtstct 0, 0, 0") + self.kstest_address_consistency("la 1, 0, 1") + self.kstest_address_consistency("subi 0, 0, 0") + self.kstest_address_consistency("subis 0, 0, 0") + self.kstest_address_consistency("subic 0, 0, 0") + self.kstest_address_consistency("subic. 0, 0, 0") + self.kstest_address_consistency("extlwi 0, 0, 0, 0") + self.kstest_address_consistency("extrwi 0, 0, 0, 0") + self.kstest_address_consistency("inslwi 0, 0, 0, 0") + self.kstest_address_consistency("insrwi 0, 0, 0, 0") + self.kstest_address_consistency("rotrwi 0, 0, 0") + self.kstest_address_consistency("slwi 0, 0, 0") + self.kstest_address_consistency("srwi 0, 0, 0") + self.kstest_address_consistency("clrrwi 0, 0, 0") + self.kstest_address_consistency("clrlslwi 0, 0, 0, 0") + self.kstest_address_consistency("extldi 0, 0, 0, 0") + self.kstest_address_consistency("extrdi 0, 0, 0, 0") + self.kstest_address_consistency("insrdi 0, 0, 0, 0") + self.kstest_address_consistency("rotrdi 0, 0, 0") + self.kstest_address_consistency("sldi 0, 0, 0") + self.kstest_address_consistency("srdi 0, 0, 0") + self.kstest_address_consistency("clrrdi 0, 0, 0") + self.kstest_address_consistency("clrlsldi 0, 0, 0, 0") + self.kstest_address_consistency("rlwinm 0, 0, 0, 1") + self.kstest_address_consistency("rlwimi 0, 0, 0, 1") + self.kstest_address_consistency("rlwnm 0, 0, 0, 1") + self.kstest_address_consistency("mftb 0, 0") From 0dd7d7ef272cfd8371c52b1cb120fd876fee9f08 Mon Sep 17 00:00:00 2001 From: Ed Larson Date: Mon, 15 Jul 2019 16:50:20 -0400 Subject: [PATCH 10/12] Remove bounds check on ppc branch instructions target address (fix issue 423) (cherry picked from commit 06afb493e09cb7591fedf17cc5b06f9a865b385c) --- .../Target/PowerPC/AsmParser/PPCAsmParser.cpp | 24 +++-------- suite/regress/ppc_branch_addressing.py | 43 +++++++++++++++++++ 2 files changed, 49 insertions(+), 18 deletions(-) create mode 100644 suite/regress/ppc_branch_addressing.py diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp index e3b18853..008efcd4 100644 --- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -503,25 +503,13 @@ struct PPCOperand : public MCParsedAsmOperand { } bool isTLSReg() const { return Kind == TLSRegister; } bool isDirectBr() const { - if (Kind == Expression) - return true; - if (Kind != Immediate) - return false; - // Operand must be 64-bit aligned, signed 27-bit immediate. - if ((getImm() & 3) != 0) - return false; - if (isInt<26>(getImm())) - return true; - if (!IsPPC64) { - // In 32-bit mode, large 32-bit quantities wrap around. - if (isUInt<32>(getImm()) && isInt<26>(static_cast(getImm()))) - return true; - } - return false; + return (Kind == Expression) + ||((Kind == Immediate) && ((getImm() & 3) == 0)); + } + bool isCondBr() const { + return (Kind == Expression) + ||((Kind == Immediate) && ((getImm() & 3) == 0)); } - bool isCondBr() const { return Kind == Expression || - (Kind == Immediate && isInt<16>(getImm()) && - (getImm() & 3) == 0); } bool isRegNumber() const { return Kind == Immediate && isUInt<5>(getImm()); } bool isVSRegNumber() const { return Kind == Immediate && isUInt<6>(getImm()); } bool isCCRegNumber() const { return (Kind == Expression diff --git a/suite/regress/ppc_branch_addressing.py b/suite/regress/ppc_branch_addressing.py new file mode 100644 index 00000000..84cebcbb --- /dev/null +++ b/suite/regress/ppc_branch_addressing.py @@ -0,0 +1,43 @@ +from keystone import * +import regress + +# Github issue: #423 +# Author: Edward Larson + +class TestBranchRelativeAddressing(regress.RegressTest): + def kstest(self, arch, mode, code, expect, syntax = 0, address = 0): + ks = Ks(arch, mode) + if syntax != 0: + ks.syntax = syntax + encoding, count = ks.asm(code, address) + self.assertEqual(expect, encoding) + + def runTest(self): + # 0x1fffffc is largest positive branch offset in PPC, 0x2000000 is largest negative branch offset + self.kstest(KS_ARCH_PPC, KS_MODE_PPC32 | KS_MODE_BIG_ENDIAN, b"b 0x1fffffc", [0x49, 0xff, 0xff, 0xfc], address=0x0) + self.kstest(KS_ARCH_PPC, KS_MODE_PPC32 | KS_MODE_BIG_ENDIAN, b"b 0x2000000", [0x49, 0xff, 0xff, 0xfc], address=0x4) + self.kstest(KS_ARCH_PPC, KS_MODE_PPC32 | KS_MODE_BIG_ENDIAN, b"b 0x0", [0x4a, 0x00, 0x00, 0x00], address=0x2000000) + # beyond max positive range, branch will wrap around to negative + self.kstest(KS_ARCH_PPC, KS_MODE_PPC32 | KS_MODE_BIG_ENDIAN, b"b 0x2000000", [0x4a, 0, 0, 0], address=0x0) + # beyond max negative range, branch will wrap ardound to positive + self.kstest(KS_ARCH_PPC, KS_MODE_PPC32 | KS_MODE_BIG_ENDIAN, b"b 0x0", [0x49, 0xff, 0xff, 0xfc], address=0x2000004) + + +class TestBranchAbsoluteAddressing(regress.RegressTest): + def kstest(self, arch, mode, code, expect, syntax = 0, address = 0): + ks = Ks(arch, mode) + if syntax != 0: + ks.syntax = syntax + encoding, count = ks.asm(code, address) + self.assertEqual(expect, encoding) + + def runTest(self): + # 0x1fffffc is largest absolute offset in PPC + self.kstest(KS_ARCH_PPC, KS_MODE_PPC32 | KS_MODE_BIG_ENDIAN, b"ba 0x1fffffc", [0x49, 0xff, 0xff, 0xfe], address=0x0) + self.kstest(KS_ARCH_PPC, KS_MODE_PPC32 | KS_MODE_BIG_ENDIAN, b"ba 0x1fffffc", [0x49, 0xff, 0xff, 0xfe], address=0x4) + # beyond max positive range, branch will wrap around to negative + self.kstest(KS_ARCH_PPC, KS_MODE_PPC32 | KS_MODE_BIG_ENDIAN, b"ba 0x2000000", [0x4a, 0, 0, 2], address=0x0) + + +if __name__ == '__main__': + regress.main() \ No newline at end of file From 54174e101445c40180f7caa753a9da47ac0cbac9 Mon Sep 17 00:00:00 2001 From: Ed Larson Date: Fri, 2 Aug 2019 13:39:13 -0400 Subject: [PATCH 11/12] Clean up test for issue #427 --- suite/regress/ppc_address_consistency.py | 25 ++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/suite/regress/ppc_address_consistency.py b/suite/regress/ppc_address_consistency.py index d371aa58..a58a6d0c 100644 --- a/suite/regress/ppc_address_consistency.py +++ b/suite/regress/ppc_address_consistency.py @@ -1,25 +1,30 @@ from keystone import * import regress +# Github issue #427 # Author: Edward Larson class TestAddressConsistency(regress.RegressTest): - def kstest_address_consistency(self, inst_assembly): + def kstest_address_consistency(self, preceding_assembly, start_address=0x1000, branch_address=0x1004): + """ + Check that a relative branch to itself at branch_address emits the same machine code, independent of the + inst_Assembly comes before it. + :param preceding_assembly: Instruction(s) to be assembled before the branch instruction + :param start_address: VM address of the beginning of preceding_assembly + :param branch_address: VM address of the branch instruction + :return: + """ ks = Ks(KS_ARCH_PPC, KS_MODE_32 | KS_MODE_BIG_ENDIAN) + branch_assembly = 'b ' + hex(branch_address) + expected_branch_encoding, _ = ks.asm(branch_assembly, branch_address) - # relative branch to its own address should always be encoded with branch target 0 - start_address = 0x1000 - branch_assembly = "b 0x1004" - branch_mc = [0x48, 0x00, 0x00, 0x00] - - code = inst_assembly + "; " + branch_assembly + code = preceding_assembly + "; " + branch_assembly encoding, count = ks.asm(code, start_address) + emitted_branch_encoding = encoding[-4:] - last_instruction_mc = encoding[-4:] - - self.assertEqual(branch_mc, last_instruction_mc) + self.assertEqual(emitted_branch_encoding, expected_branch_encoding) def runTest(self): # un-aliased instructions From e729dffa101a7891fb3ce93c7800659c4b337406 Mon Sep 17 00:00:00 2001 From: brendabrandy Date: Fri, 18 Oct 2019 15:00:08 -0400 Subject: [PATCH 12/12] implement several ARM subarchitectures as modes available under ARM --- bindings/python/keystone/keystone_const.py | 3 +++ bindings/python/sample.py | 8 +++++- include/keystone/keystone.h | 3 +++ kstool/kstool.cpp | 31 ++++++++++++++++++++++ kstool/test-all.sh | 31 ++++++++++++++++++++++ llvm/keystone/ks.cpp | 20 +++++++++++++- llvm/keystone/ks_priv.h | 2 +- samples/sample.c | 8 +++++- suite/regress/test_all_archs.py | 8 +++++- suite/test-all.sh | 30 +++++++++++++++++++++ 10 files changed, 139 insertions(+), 5 deletions(-) diff --git a/bindings/python/keystone/keystone_const.py b/bindings/python/keystone/keystone_const.py index d97deb24..bbbb8ba9 100644 --- a/bindings/python/keystone/keystone_const.py +++ b/bindings/python/keystone/keystone_const.py @@ -20,6 +20,9 @@ KS_MODE_ARM = 1 KS_MODE_THUMB = 16 KS_MODE_V8 = 64 +KS_MODE_V4 = 128 +KS_MODE_XSCALE = 256 +KS_MODE_V5 = 512 KS_MODE_MICRO = 16 KS_MODE_MIPS3 = 32 KS_MODE_MIPS32R6 = 64 diff --git a/bindings/python/sample.py b/bindings/python/sample.py index 6ee9f889..6633ffea 100755 --- a/bindings/python/sample.py +++ b/bindings/python/sample.py @@ -69,7 +69,13 @@ def sym_resolver(symbol, value): test_ks(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_BIG_ENDIAN, b"sub r1, r2, r5") test_ks(KS_ARCH_ARM, KS_MODE_THUMB, b"movs r4, #0xf0") test_ks(KS_ARCH_ARM, KS_MODE_THUMB + KS_MODE_BIG_ENDIAN, b"movs r4, #0xf0") - + test_ks(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_V4, b"nop") + test_ks(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_BIG_ENDIAN + KS_MODE_V4, b"nop") + test_ks(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_XSCALE, b"nop") + test_ks(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_BIG_ENDIAN + KS_MODE_XSCALE, b"nop") + test_ks(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_V5, b"nop") + test_ks(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_BIG_ENDIAN + KS_MODE_V5, b"nop") + # ARM64 test_ks(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN, b"ldr w1, [sp, #0x8]") diff --git a/include/keystone/keystone.h b/include/keystone/keystone.h index 87305c97..f131b230 100644 --- a/include/keystone/keystone.h +++ b/include/keystone/keystone.h @@ -68,6 +68,9 @@ typedef enum ks_mode { KS_MODE_ARM = 1 << 0, // ARM mode KS_MODE_THUMB = 1 << 4, // THUMB mode (including Thumb-2) KS_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM + KS_MODE_V4 = 1 << 7, + KS_MODE_XSCALE = 1 << 8, + KS_MODE_V5 = 1 << 9, // mips KS_MODE_MICRO = 1 << 4, // MicroMips mode KS_MODE_MIPS3 = 1 << 5, // Mips III ISA diff --git a/kstool/kstool.cpp b/kstool/kstool.cpp index 7bf57a63..cf083220 100644 --- a/kstool/kstool.cpp +++ b/kstool/kstool.cpp @@ -36,6 +36,12 @@ static void usage(char *prog) if (ks_arch_supported(KS_ARCH_ARM)) { printf(" arm: ARM - little endian\n"); printf(" armbe: ARM - big endian\n"); + printf(" armv4t: ARM V4T - little endian\n"); + printf(" armv4tbe: ARM V4T - big endian\n"); + printf(" armv5: ARM V5 - little endian\n"); + printf(" armv5be: ARM V5 - big endian\n"); + printf(" xscale: XSCALE - little endian\n"); + printf(" xscale: XSCALE - big endian\n"); printf(" thumb: Thumb - little endian\n"); printf(" thumbbe: Thumb - big endian\n"); printf(" armv8: ARM V8 - little endian\n"); @@ -208,6 +214,31 @@ int main(int argc, char **argv) err = ks_open(KS_ARCH_ARM, KS_MODE_ARM+KS_MODE_BIG_ENDIAN, &ks); } + if (!strcmp(mode, "xscale")) { + err = ks_open(KS_ARCH_ARM, KS_MODE_XSCALE+KS_MODE_LITTLE_ENDIAN+KS_MODE_ARM, &ks); + } + + if (!strcmp(mode, "xscalebe")) { + err = ks_open(KS_ARCH_ARM, KS_MODE_XSCALE+KS_MODE_BIG_ENDIAN+KS_MODE_ARM, &ks); + } + + if (!strcmp(mode, "armv4t")) { + err = ks_open(KS_ARCH_ARM, KS_MODE_V4+KS_MODE_LITTLE_ENDIAN+KS_MODE_ARM, &ks); + } + + if (!strcmp(mode, "armv4tbe")) { + err = ks_open(KS_ARCH_ARM, KS_MODE_V4+KS_MODE_BIG_ENDIAN+KS_MODE_ARM, &ks); + } + + if (!strcmp(mode, "armv5")) { + err = ks_open(KS_ARCH_ARM, KS_MODE_V5+KS_MODE_LITTLE_ENDIAN+KS_MODE_ARM, &ks); + } + + if (!strcmp(mode, "armv5be")) { + err = ks_open(KS_ARCH_ARM, KS_MODE_V5+KS_MODE_BIG_ENDIAN+KS_MODE_ARM, &ks); + } + + if (!strcmp(mode, "thumb")) { err = ks_open(KS_ARCH_ARM, KS_MODE_THUMB+KS_MODE_LITTLE_ENDIAN, &ks); } diff --git a/kstool/test-all.sh b/kstool/test-all.sh index efbead76..911eff8b 100755 --- a/kstool/test-all.sh +++ b/kstool/test-all.sh @@ -30,6 +30,37 @@ kstool armbe "sub r1, r2, r5" #encoding: [0x05,0x10,0x42,0xe0] echo +echo "::XScale" +kstool xscale "nop" +#encoding: [0x00, 0x00, 0xa0, 0xe1] +echo + +echo "::XScale BE" +kstool xscalebe "nop" +#encoding: [0xe1, 0xa0, 0x00, 0x00] +echo + +echo "::ARMv4t" +kstool armv4t "nop" +#encoding: [0x00, 0x00, 0xa0, 0xe1] +echo + +echo "::ARMv4t BE" +kstool armv4tbe "nop" +#encoding: [0xe1, 0xa0, 0x00, 0x00] +echo + +echo "::ARMv5" +kstool armv5 "nop" +#encoding: [0x00, 0x00, 0xa0, 0xe1] +echo + +echo "::ARMv5 BE" +kstool armv5be "nop" +#encoding: [0xe1, 0xa0, 0x00, 0x00] +echo + + echo "::Thumb LE" kstool thumb "movs r4, #0xf0" #encoding: [0xf0,0x24] diff --git a/llvm/keystone/ks.cpp b/llvm/keystone/ks.cpp index 5303a443..7e417178 100644 --- a/llvm/keystone/ks.cpp +++ b/llvm/keystone/ks.cpp @@ -293,7 +293,16 @@ ks_err ks_open(ks_arch arch, int mode, ks_engine **result) case KS_MODE_BIG_ENDIAN | KS_MODE_THUMB: TripleName = "thumbebv7"; break; - + case KS_MODE_BIG_ENDIAN | KS_MODE_V4 | KS_MODE_ARM: + TripleName = "armv4teb"; + break; + case KS_MODE_BIG_ENDIAN | KS_MODE_XSCALE | KS_MODE_ARM: + TripleName = "xscaleeb"; + break; + case KS_MODE_BIG_ENDIAN | KS_MODE_V5 | KS_MODE_ARM: + TripleName = "armv5eb"; + break; + // little-endian case KS_MODE_LITTLE_ENDIAN | KS_MODE_V8 | KS_MODE_ARM: TripleName = "armv8"; @@ -307,6 +316,15 @@ ks_err ks_open(ks_arch arch, int mode, ks_engine **result) case KS_MODE_LITTLE_ENDIAN | KS_MODE_THUMB: TripleName = "thumbv7"; break; + case KS_MODE_LITTLE_ENDIAN | KS_MODE_V4 | KS_MODE_ARM: + TripleName = "armv4t"; + break; + case KS_MODE_LITTLE_ENDIAN | KS_MODE_XSCALE | KS_MODE_ARM: + TripleName = "xscale"; + break; + case KS_MODE_LITTLE_ENDIAN | KS_MODE_V5 | KS_MODE_ARM: + TripleName = "armv5"; + break; } InitKs(arch, ks, TripleName); diff --git a/llvm/keystone/ks_priv.h b/llvm/keystone/ks_priv.h index 1a2b3c1e..4aa2ca7b 100644 --- a/llvm/keystone/ks_priv.h +++ b/llvm/keystone/ks_priv.h @@ -20,7 +20,7 @@ // These are masks of supported modes for each cpu/arch. // They should be updated when changes are made to the ks_mode enum typedef. -#define KS_MODE_ARM_MASK (KS_MODE_ARM|KS_MODE_THUMB|KS_MODE_LITTLE_ENDIAN|KS_MODE_BIG_ENDIAN|KS_MODE_V8) +#define KS_MODE_ARM_MASK (KS_MODE_ARM|KS_MODE_THUMB|KS_MODE_LITTLE_ENDIAN|KS_MODE_BIG_ENDIAN|KS_MODE_V8|KS_MODE_V4|KS_MODE_XSCALE|KS_MODE_V5) #define KS_MODE_MIPS_MASK (KS_MODE_MIPS32|KS_MODE_MIPS64|KS_MODE_LITTLE_ENDIAN|KS_MODE_BIG_ENDIAN) #define KS_MODE_X86_MASK (KS_MODE_16|KS_MODE_32|KS_MODE_64|KS_MODE_LITTLE_ENDIAN) #define KS_MODE_PPC_MASK (KS_MODE_PPC32|KS_MODE_PPC64|KS_MODE_LITTLE_ENDIAN|KS_MODE_BIG_ENDIAN) diff --git a/samples/sample.c b/samples/sample.c index ea82e010..48e1c79f 100644 --- a/samples/sample.c +++ b/samples/sample.c @@ -124,7 +124,13 @@ int main(int argc, char **argv) test_ks(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_BIG_ENDIAN, "sub r1, r2, r5", 0); test_ks(KS_ARCH_ARM, KS_MODE_THUMB, "movs r4, #0xf0", 0); test_ks(KS_ARCH_ARM, KS_MODE_THUMB + KS_MODE_BIG_ENDIAN, "movs r4, #0xf0", 0); - + test_ks(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_V4, "nop", 0); + test_ks(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_BIG_ENDIAN + KS_MODE_V4, "nop", 0); + test_ks(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_XSCALE, "nop", 0); + test_ks(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_BIG_ENDIAN + KS_MODE_XSCALE, "nop", 0); + test_ks(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_V5, "nop", 0); + test_ks(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_BIG_ENDIAN + KS_MODE_V5, "nop", 0); + // ARM64 test_ks(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN, "ldr w1, [sp, #0x8]", 0); diff --git a/suite/regress/test_all_archs.py b/suite/regress/test_all_archs.py index 916511bd..6daee669 100755 --- a/suite/regress/test_all_archs.py +++ b/suite/regress/test_all_archs.py @@ -36,7 +36,13 @@ def runTest(self): self.kstest(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_BIG_ENDIAN, b"sub r1, r2, r5", [ 0xe0, 0x42, 0x10, 0x05 ]) self.kstest(KS_ARCH_ARM, KS_MODE_THUMB, b"movs r4, #0xf0", [ 0xf0, 0x24 ]) self.kstest(KS_ARCH_ARM, KS_MODE_THUMB + KS_MODE_BIG_ENDIAN, b"movs r4, #0xf0", [ 0x24, 0xf0 ]) - + self.kstest(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_XSCALE, b"nop", [ 0x00, 0x00, 0xa0, 0xe1 ]) + self.kstest(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_BIG_ENDIAN + KS_MODE_XSCALE, b"nop", [ 0xe1, 0xa0, 0x00, 0x00 ]) + self.kstest(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_V4, b"nop", [ 0x00, 0x00, 0xa0, 0xe1 ]) + self.kstest(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_BIG_ENDIAN + KS_MODE_V4, b"nop", [ 0xe1, 0xa0, 0x00, 0x00 ]) + self.kstest(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_V5, b"nop", [ 0x00, 0x00, 0xa0, 0xe1 ]) + self.kstest(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_BIG_ENDIAN + KS_MODE_V5, b"nop", [ 0xe1, 0xa0, 0x00, 0x00 ]) + # ARM64 self.kstest(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN, b"ldr w1, [sp, #0x8]", [ 0xe1, 0x0b, 0x40, 0xb9 ]) diff --git a/suite/test-all.sh b/suite/test-all.sh index efbead76..d1b3b2eb 100755 --- a/suite/test-all.sh +++ b/suite/test-all.sh @@ -30,6 +30,36 @@ kstool armbe "sub r1, r2, r5" #encoding: [0x05,0x10,0x42,0xe0] echo +echo "::XScale" +kstool xscale "nop" +#encoding: [0x00, 0x00, 0xa0, 0xe1] +echo + +echo "::XScale BE" +kstool xscalebe "nop" +#encoding: [0xe1, 0xa0, 0x00, 0x00] +echo + +echo "::ARMv4t" +kstool armv4t "nop" +#encoding: [0x00, 0x00, 0xa0, 0xe1] +echo + +echo "::ARMv4t BE" +kstool armv4tbe "nop" +#encoding: [0xe1, 0xa0, 0x00, 0x00] +echo + +echo "::ARMv5" +kstool armv5 "nop" +#encoding: [0x00, 0x00, 0xa0, 0xe1] +echo + +echo "::ARMv5 BE" +kstool armv5be "nop" +#encoding: [0xe1, 0xa0, 0x00, 0x00] +echo + echo "::Thumb LE" kstool thumb "movs r4, #0xf0" #encoding: [0xf0,0x24]