Skip to content

Commit c850db1

Browse files
committed
Inherit architecture support from cfg features
While the bindings conditionally compile code based on the cfg flags, we still include the architecture support in emitted rust code. This patch removes the ability to refer to architectures that cannot possibly be supported.
1 parent 30b9960 commit c850db1

File tree

1 file changed

+95
-40
lines changed

1 file changed

+95
-40
lines changed

bindings/rust/src/lib.rs

+95-40
Original file line numberDiff line numberDiff line change
@@ -42,32 +42,72 @@ use libc::c_void;
4242

4343
use ffi::uc_handle;
4444

45-
pub use crate::arm::*;
46-
pub use crate::arm64::*;
47-
pub use crate::m68k::*;
48-
pub use crate::mips::*;
49-
pub use crate::ppc::*;
50-
pub use crate::riscv::*;
51-
pub use crate::s390x::*;
52-
pub use crate::sparc::*;
53-
pub use crate::tricore::*;
54-
pub use crate::unicorn_const::*;
55-
pub use crate::x86::*;
56-
5745
#[macro_use]
5846
pub mod unicorn_const;
47+
pub use unicorn_const::*;
5948
pub mod ffi; // lets consumers call ffi if desired
6049

50+
// include arm support if conditionally compiled in
51+
#[cfg(feature = "arch_arm")]
6152
mod arm;
53+
#[cfg(feature = "arch_arm")]
54+
pub use crate::arm::*;
55+
56+
// include arm64 support if conditionally compiled in
57+
// NOTE: unicorn-c only separates on top-level arch name,
58+
// not on the bit-length, so we include both
59+
#[cfg(feature = "arch_arm")]
6260
mod arm64;
61+
#[cfg(feature = "arch_arm")]
62+
pub use crate::arm64::*;
63+
64+
// include m68k support if conditionally compiled in
65+
#[cfg(feature = "arch_m68k")]
6366
mod m68k;
67+
#[cfg(feature = "arch_m68k")]
68+
pub use crate::m68k::*;
69+
70+
// include mips support if conditionally compiled in
71+
#[cfg(feature = "arch_mips")]
6472
mod mips;
73+
#[cfg(feature = "arch_mips")]
74+
pub use crate::mips::*;
75+
76+
// include ppc support if conditionally compiled in
77+
#[cfg(feature = "arch_ppc")]
6578
mod ppc;
79+
#[cfg(feature = "arch_ppc")]
80+
pub use crate::ppc::*;
81+
82+
// include riscv support if conditionally compiled in
83+
#[cfg(feature = "arch_riscv")]
6684
mod riscv;
85+
#[cfg(feature = "arch_riscv")]
86+
pub use crate::riscv::*;
87+
88+
// include s390x support if conditionally compiled in
89+
#[cfg(feature = "arch_s390x")]
6790
mod s390x;
91+
#[cfg(feature = "arch_s390x")]
92+
pub use crate::s390x::*;
93+
94+
// include sparc support if conditionally compiled in
95+
#[cfg(feature = "arch_sparc")]
6896
mod sparc;
97+
#[cfg(feature = "arch_sparc")]
98+
pub use crate::sparc::*;
99+
100+
// include tricore support if conditionally compiled in
101+
#[cfg(feature = "arch_tricore")]
69102
mod tricore;
103+
#[cfg(feature = "arch_tricore")]
104+
pub use crate::tricore::*;
105+
106+
// include x86 support if conditionally compiled in
107+
#[cfg(feature = "arch_x86")]
70108
mod x86;
109+
#[cfg(feature = "arch_x86")]
110+
pub use crate::x86::*;
71111

72112
#[derive(Debug)]
73113
pub struct Context {
@@ -508,7 +548,9 @@ impl<'a, D> Unicorn<'a, D> {
508548
let curr_arch = self.get_arch();
509549

510550
let value_size = match curr_arch {
551+
#[cfg(feature = "arch_x86")]
511552
Arch::X86 => Self::value_size_x86(curr_reg_id)?,
553+
#[cfg(feature = "arch_arm")]
512554
Arch::ARM64 => Self::value_size_arm64(curr_reg_id)?,
513555
_ => Err(uc_error::ARCH)?,
514556
};
@@ -517,6 +559,7 @@ impl<'a, D> Unicorn<'a, D> {
517559
.and_then(|| Ok(value.into_boxed_slice()))
518560
}
519561

562+
#[cfg(feature = "arch_arm")]
520563
fn value_size_arm64(curr_reg_id: i32) -> Result<usize, uc_error> {
521564
match curr_reg_id {
522565
r if (RegisterARM64::Q0 as i32..=RegisterARM64::Q31 as i32).contains(&r)
@@ -528,6 +571,7 @@ impl<'a, D> Unicorn<'a, D> {
528571
}
529572
}
530573

574+
#[cfg(feature = "arch_x86")]
531575
fn value_size_x86(curr_reg_id: i32) -> Result<usize, uc_error> {
532576
match curr_reg_id {
533577
r if (RegisterX86::XMM0 as i32..=RegisterX86::XMM31 as i32).contains(&r) => Ok(16),
@@ -716,6 +760,7 @@ impl<'a, D> Unicorn<'a, D> {
716760
}
717761

718762
/// Add hook for x86 IN instruction.
763+
#[cfg(feature = "arch_x86")]
719764
pub fn add_insn_in_hook<F: 'a>(&mut self, callback: F) -> Result<UcHookId, uc_error>
720765
where
721766
F: FnMut(&mut Unicorn<D>, u32, usize) -> u32,
@@ -746,6 +791,7 @@ impl<'a, D> Unicorn<'a, D> {
746791
}
747792

748793
/// Add hook for x86 OUT instruction.
794+
#[cfg(feature = "arch_x86")]
749795
pub fn add_insn_out_hook<F: 'a>(&mut self, callback: F) -> Result<UcHookId, uc_error>
750796
where
751797
F: FnMut(&mut Unicorn<D>, u32, usize, u32),
@@ -776,6 +822,7 @@ impl<'a, D> Unicorn<'a, D> {
776822
}
777823

778824
/// Add hook for x86 SYSCALL or SYSENTER.
825+
#[cfg(feature = "arch_x86")]
779826
pub fn add_insn_sys_hook<F>(
780827
&mut self,
781828
insn_type: InsnSysX86,
@@ -932,44 +979,52 @@ impl<'a, D> Unicorn<'a, D> {
932979
unsafe { ffi::uc_query(self.get_handle(), query, &mut result) }.and(Ok(result))
933980
}
934981

982+
/// Get the `i32` register value for the program counter for the specified architecture.
983+
///
984+
/// If an architecture is not compiled in, this function will return `uc_error::ARCH`.
985+
#[inline]
986+
fn arch_to_pc_register(arch: Arch) -> Result<i32, uc_error> {
987+
match arch {
988+
#[cfg(feature = "arch_x86")]
989+
Arch::X86 => Ok(RegisterX86::RIP as i32),
990+
#[cfg(feature = "arch_arm")]
991+
Arch::ARM => Ok(RegisterARM::PC as i32),
992+
#[cfg(feature = "arch_arm")]
993+
Arch::ARM64 => Ok(RegisterARM64::PC as i32),
994+
#[cfg(feature = "arch_mips")]
995+
Arch::MIPS => Ok(RegisterMIPS::PC as i32),
996+
#[cfg(feature = "arch_sparc")]
997+
Arch::SPARC => Ok(RegisterSPARC::PC as i32),
998+
#[cfg(feature = "arch_m68k")]
999+
Arch::M68K => Ok(RegisterM68K::PC as i32),
1000+
#[cfg(feature = "arch_ppc")]
1001+
Arch::PPC => Ok(RegisterPPC::PC as i32),
1002+
#[cfg(feature = "arch_riscv")]
1003+
Arch::RISCV => Ok(RegisterRISCV::PC as i32),
1004+
#[cfg(feature = "arch_s390x")]
1005+
Arch::S390X => Ok(RegisterS390X::PC as i32),
1006+
#[cfg(feature = "arch_tricore")]
1007+
Arch::TRICORE => Ok(RegisterTRICORE::PC as i32),
1008+
// returns `uc_error::ARCH` for `Arch::MAX`, and any
1009+
// other architecture that are not compiled in
1010+
_ => Err(uc_error::ARCH),
1011+
}
1012+
}
1013+
9351014
/// Gets the current program counter for this `unicorn` instance.
9361015
#[inline]
9371016
pub fn pc_read(&self) -> Result<u64, uc_error> {
9381017
let arch = self.get_arch();
939-
let reg = match arch {
940-
Arch::X86 => RegisterX86::RIP as i32,
941-
Arch::ARM => RegisterARM::PC as i32,
942-
Arch::ARM64 => RegisterARM64::PC as i32,
943-
Arch::MIPS => RegisterMIPS::PC as i32,
944-
Arch::SPARC => RegisterSPARC::PC as i32,
945-
Arch::M68K => RegisterM68K::PC as i32,
946-
Arch::PPC => RegisterPPC::PC as i32,
947-
Arch::RISCV => RegisterRISCV::PC as i32,
948-
Arch::S390X => RegisterS390X::PC as i32,
949-
Arch::TRICORE => RegisterTRICORE::PC as i32,
950-
Arch::MAX => panic!("Illegal Arch specified"),
951-
};
952-
self.reg_read(reg)
1018+
1019+
self.reg_read(Self::arch_to_pc_register(arch)?)
9531020
}
9541021

9551022
/// Sets the program counter for this `unicorn` instance.
9561023
#[inline]
9571024
pub fn set_pc(&mut self, value: u64) -> Result<(), uc_error> {
9581025
let arch = self.get_arch();
959-
let reg = match arch {
960-
Arch::X86 => RegisterX86::RIP as i32,
961-
Arch::ARM => RegisterARM::PC as i32,
962-
Arch::ARM64 => RegisterARM64::PC as i32,
963-
Arch::MIPS => RegisterMIPS::PC as i32,
964-
Arch::SPARC => RegisterSPARC::PC as i32,
965-
Arch::M68K => RegisterM68K::PC as i32,
966-
Arch::PPC => RegisterPPC::PC as i32,
967-
Arch::RISCV => RegisterRISCV::PC as i32,
968-
Arch::S390X => RegisterS390X::PC as i32,
969-
Arch::TRICORE => RegisterTRICORE::PC as i32,
970-
Arch::MAX => panic!("Illegal Arch specified"),
971-
};
972-
self.reg_write(reg, value)
1026+
1027+
self.reg_write(Self::arch_to_pc_register(arch)?, value)
9731028
}
9741029

9751030
pub fn ctl_get_mode(&self) -> Result<Mode, uc_error> {

0 commit comments

Comments
 (0)