From 829b5049e6bb919f7c821544ac3e6ca1165eba8b Mon Sep 17 00:00:00 2001 From: Ivan Fratric Date: Tue, 4 Jul 2023 11:08:36 +0200 Subject: [PATCH] Hexagon support (#1323) * Hexagon support * Fix format * Fix needless bool * Address comments --------- Co-authored-by: Andrea Fioraldi --- libafl_qemu/Cargo.toml | 4 +- libafl_qemu/build_linux.rs | 9 ++- libafl_qemu/libafl_qemu_build/src/build.rs | 2 +- libafl_qemu/libafl_qemu_sys/Cargo.toml | 1 + libafl_qemu/libafl_qemu_sys/build_linux.rs | 6 +- libafl_qemu/src/calls.rs | 7 +++ libafl_qemu/src/hexagon.rs | 68 ++++++++++++++++++++++ libafl_qemu/src/lib.rs | 19 ++++-- 8 files changed, 104 insertions(+), 12 deletions(-) create mode 100644 libafl_qemu/src/hexagon.rs diff --git a/libafl_qemu/Cargo.toml b/libafl_qemu/Cargo.toml index d8574a0389..b3e6a14baf 100644 --- a/libafl_qemu/Cargo.toml +++ b/libafl_qemu/Cargo.toml @@ -12,9 +12,10 @@ edition = "2021" categories = ["development-tools::testing", "emulators", "embedded", "os", "no-std"] [features] -default = ["fork"] +default = ["fork", "build_libqasan"] python = ["pyo3", "pyo3-build-config"] fork = ["libafl/fork"] +build_libqasan = [] # The following architecture features are mutually exclusive. x86_64 = ["libafl_qemu_sys/x86_64"] # build qemu for x86_64 (default) @@ -23,6 +24,7 @@ arm = ["libafl_qemu_sys/arm"] # build qemu for arm aarch64 = ["libafl_qemu_sys/aarch64"] # build qemu for aarch64 mips = ["libafl_qemu_sys/mips"] # build qemu for mips (el, use with the 'be' feature of mips be) ppc = ["libafl_qemu_sys/ppc"] # build qemu for powerpc +hexagon = ["libafl_qemu_sys/hexagon"] # build qemu for hexagon be = ["libafl_qemu_sys/be"] diff --git a/libafl_qemu/build_linux.rs b/libafl_qemu/build_linux.rs index 625f9ebae9..ba808ea9a1 100644 --- a/libafl_qemu/build_linux.rs +++ b/libafl_qemu/build_linux.rs @@ -12,6 +12,9 @@ pub fn build() { "usermode".to_string() }) }; + + let build_libqasan = cfg!(all(feature = "build_libqasan", not(feature = "hexagon"))); + println!("cargo:rustc-cfg=emulation_mode=\"{emulation_mode}\""); println!("cargo:rerun-if-env-changed=EMULATION_MODE"); @@ -30,6 +33,8 @@ pub fn build() { "mips".to_string() } else if cfg!(feature = "ppc") { "ppc".to_string() + } else if cfg!(feature = "hexagon") { + "hexagon".to_string() } else { env::var("CPU_TARGET").unwrap_or_else(|_| { "x86_64".to_string() @@ -38,7 +43,7 @@ pub fn build() { println!("cargo:rerun-if-env-changed=CPU_TARGET"); println!("cargo:rustc-cfg=cpu_target=\"{cpu_target}\""); - let cross_cc = if emulation_mode == "usermode" { + let cross_cc = if (emulation_mode == "usermode") && build_libqasan { // TODO try to autodetect a cross compiler with the arch name (e.g. aarch64-linux-gnu-gcc) let cross_cc = env::var("CROSS_CC").unwrap_or_else(|_| { println!("cargo:warning=CROSS_CC is not set, default to cc (things can go wrong if the selected cpu target ({cpu_target}) is not the host arch ({}))", env::consts::ARCH); @@ -62,7 +67,7 @@ pub fn build() { target_dir.pop(); target_dir.pop(); - if emulation_mode == "usermode" { + if (emulation_mode == "usermode") && build_libqasan { let qasan_dir = Path::new("libqasan"); let qasan_dir = fs::canonicalize(qasan_dir).unwrap(); diff --git a/libafl_qemu/libafl_qemu_build/src/build.rs b/libafl_qemu/libafl_qemu_build/src/build.rs index 86e4ed110e..5e91f812cb 100644 --- a/libafl_qemu/libafl_qemu_build/src/build.rs +++ b/libafl_qemu/libafl_qemu_build/src/build.rs @@ -8,7 +8,7 @@ use which::which; const QEMU_URL: &str = "https://github.com/AFLplusplus/qemu-libafl-bridge"; const QEMU_DIRNAME: &str = "qemu-libafl-bridge"; -const QEMU_REVISION: &str = "9302a3a8174a45a14c77be316126f2673248be51"; +const QEMU_REVISION: &str = "98efc72c4ca20b60c80dd16e2c88af114b8b2ae7"; fn build_dep_check(tools: &[&str]) { for tool in tools { diff --git a/libafl_qemu/libafl_qemu_sys/Cargo.toml b/libafl_qemu/libafl_qemu_sys/Cargo.toml index a8dc87e1f1..d3bd59f4f2 100644 --- a/libafl_qemu/libafl_qemu_sys/Cargo.toml +++ b/libafl_qemu/libafl_qemu_sys/Cargo.toml @@ -19,6 +19,7 @@ arm = [] # build qemu for arm aarch64 = [] # build qemu for aarch64 mips = [] # build qemu for mips (el, use with the 'be' feature of mips be) ppc = [] # build qemu for powerpc +hexagon = [] # build qemu for hexagon be = [] diff --git a/libafl_qemu/libafl_qemu_sys/build_linux.rs b/libafl_qemu/libafl_qemu_sys/build_linux.rs index 871c9a2b97..ca126db808 100644 --- a/libafl_qemu/libafl_qemu_sys/build_linux.rs +++ b/libafl_qemu/libafl_qemu_sys/build_linux.rs @@ -38,12 +38,12 @@ pub fn build() { // Make sure we have at most one architecutre feature set // Else, we default to `x86_64` - having a default makes CI easier :) - assert_unique_feature!("arm", "aarch64", "i386", "i86_64", "mips", "ppc"); + assert_unique_feature!("arm", "aarch64", "i386", "i86_64", "mips", "ppc", "hexagon"); // Make sure that we don't have BE set for any architecture other than arm and mips // Sure aarch64 may support BE, but its not in common usage and we don't // need it yet and so haven't tested it - assert_unique_feature!("be", "aarch64", "i386", "i86_64"); + assert_unique_feature!("be", "aarch64", "i386", "i86_64", "hexagon"); let cpu_target = if cfg!(feature = "x86_64") { "x86_64".to_string() @@ -57,6 +57,8 @@ pub fn build() { "mips".to_string() } else if cfg!(feature = "ppc") { "ppc".to_string() + } else if cfg!(feature = "hexagon") { + "hexagon".to_string() } else { env::var("CPU_TARGET").unwrap_or_else(|_| { println!( diff --git a/libafl_qemu/src/calls.rs b/libafl_qemu/src/calls.rs index 1c68186bd8..fa94c72a61 100644 --- a/libafl_qemu/src/calls.rs +++ b/libafl_qemu/src/calls.rs @@ -281,6 +281,13 @@ where ret_addr }; + #[cfg(cpu_target = "hexagon")] + let ret_addr = { + let emu = hooks.emulator(); + let ret_addr: GuestAddr = emu.read_reg(Regs::Lr).unwrap(); + ret_addr + }; + // log::info!("RET @ 0x{:#x}", ret_addr); let mut collectors = if let Some(h) = hooks.helpers_mut().match_first_type_mut::() { diff --git a/libafl_qemu/src/hexagon.rs b/libafl_qemu/src/hexagon.rs new file mode 100644 index 0000000000..f4eadba613 --- /dev/null +++ b/libafl_qemu/src/hexagon.rs @@ -0,0 +1,68 @@ +use num_enum::{IntoPrimitive, TryFromPrimitive}; +#[cfg(feature = "python")] +use pyo3::prelude::*; +pub use strum_macros::EnumIter; + +#[derive(IntoPrimitive, TryFromPrimitive, Debug, Clone, Copy, EnumIter)] +#[repr(i32)] +pub enum Regs { + R0 = 0, + R1 = 1, + R2 = 2, + R3 = 3, + R4 = 4, + R5 = 5, + R6 = 6, + R7 = 7, + R8 = 8, + R9 = 9, + R10 = 10, + R11 = 11, + R12 = 12, + R13 = 13, + R14 = 14, + R15 = 15, + R16 = 16, + R17 = 17, + R18 = 18, + R19 = 19, + R20 = 20, + R21 = 21, + R22 = 22, + R23 = 23, + R24 = 24, + R25 = 25, + R26 = 26, + R27 = 27, + R28 = 28, + R29 = 29, + R30 = 30, + R31 = 31, + Sa0 = 32, + Lc0 = 33, + Sa1 = 34, + Lc1 = 35, + P3_0 = 36, + M0 = 38, + M1 = 39, + Usr = 40, + Pc = 41, + Ugp = 42, + Gp = 43, + Cs0 = 44, + Cs1 = 45, + UpcycleLo = 46, + UpcycleHi = 47, + Framelimit = 48, + Framekey = 49, + Pktcntlo = 50, + Pktcnthi = 51, +} + +/// alias registers +#[allow(non_upper_case_globals)] +impl Regs { + pub const Sp: Regs = Regs::R29; + pub const Fp: Regs = Regs::R30; + pub const Lr: Regs = Regs::R31; +} diff --git a/libafl_qemu/src/lib.rs b/libafl_qemu/src/lib.rs index 292c745f66..8a9d42903e 100644 --- a/libafl_qemu/src/lib.rs +++ b/libafl_qemu/src/lib.rs @@ -55,6 +55,11 @@ pub mod ppc; #[cfg(cpu_target = "ppc")] pub use ppc::*; +#[cfg(cpu_target = "hexagon")] +pub mod hexagon; +#[cfg(cpu_target = "hexagon")] +pub use hexagon::*; + pub mod elf; pub mod helper; @@ -65,22 +70,24 @@ pub use hooks::*; pub mod edges; pub use edges::QemuEdgeCoverageHelper; -#[cfg(not(cpu_target = "mips"))] +#[cfg(not(any(cpu_target = "mips", cpu_target = "hexagon")))] pub mod cmplog; -#[cfg(not(cpu_target = "mips"))] +#[cfg(not(any(cpu_target = "mips", cpu_target = "hexagon")))] pub use cmplog::QemuCmpLogHelper; -#[cfg(emulation_mode = "usermode")] +#[cfg(all(emulation_mode = "usermode", not(cpu_target = "hexagon")))] pub mod snapshot; -#[cfg(emulation_mode = "usermode")] +#[cfg(all(emulation_mode = "usermode", not(cpu_target = "hexagon")))] pub use snapshot::QemuSnapshotHelper; -#[cfg(emulation_mode = "usermode")] +#[cfg(all(emulation_mode = "usermode", not(cpu_target = "hexagon")))] pub mod asan; -#[cfg(emulation_mode = "usermode")] +#[cfg(all(emulation_mode = "usermode", not(cpu_target = "hexagon")))] pub use asan::{init_with_asan, QemuAsanHelper}; +#[cfg(not(cpu_target = "hexagon"))] pub mod calls; +#[cfg(not(cpu_target = "hexagon"))] pub mod drcov; pub mod executor;