From 4b3b9503bbf76c8c16d572d92329c2e9d0bc4fa9 Mon Sep 17 00:00:00 2001 From: jamcleod Date: Fri, 13 Dec 2024 14:44:39 -0500 Subject: [PATCH] Add support for searching for PANDA directory --- panda-rs/Cargo.toml | 2 +- panda-rs/src/plugins/mod.rs | 90 ++++++++++++++++++++++++++----------- 2 files changed, 64 insertions(+), 28 deletions(-) diff --git a/panda-rs/Cargo.toml b/panda-rs/Cargo.toml index 4314cc0..d809eba 100644 --- a/panda-rs/Cargo.toml +++ b/panda-rs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "panda-re" -version = "0.48.0" +version = "0.49.0" authors = ["Jordan McLeod ", "tnballo "] edition = "2018" description = "The official library for interfacing with PANDA (Platform for Architecture-Neutral Dynamic Analysis)" diff --git a/panda-rs/src/plugins/mod.rs b/panda-rs/src/plugins/mod.rs index 98ca508..3ff08d1 100644 --- a/panda-rs/src/plugins/mod.rs +++ b/panda-rs/src/plugins/mod.rs @@ -1,9 +1,10 @@ //! Bindings for various built-in PANDA plugins -use crate::sys::panda_require; +use crate::{sys::panda_require, ARCH_NAME}; use libloading::Symbol; +use once_cell::sync::OnceCell; use std::ffi::CString; -use std::path::Path; +use std::path::{Path, PathBuf}; pub mod cosi; pub mod glib; @@ -388,46 +389,81 @@ pub struct Plugin { lib: libloading::Library, } -#[cfg(feature = "x86_64")] -const PLUGIN_DIR: &str = "x86_64-softmmu/panda/plugins"; +const PANDA_GLOBAL_INSTALLS: &[&str] = &["/usr/local/lib/panda", "/usr/lib/panda"]; -#[cfg(feature = "i386")] -const PLUGIN_DIR: &str = "i386-softmmu/panda/plugins"; +fn get_panda_path() -> Option<&'static Path> { + static PANDA_PATH: OnceCell> = OnceCell::new(); -#[cfg(feature = "arm")] -const PLUGIN_DIR: &str = "arm-softmmu/panda/plugins"; + PANDA_PATH + .get_or_init(|| { + if let Ok(path) = std::env::var("PANDA_PATH") { + Some(PathBuf::from(path)) + } else { + for possible_path in PANDA_GLOBAL_INSTALLS { + let path = PathBuf::from(possible_path); -#[cfg(feature = "aarch64")] -const PLUGIN_DIR: &str = "aarch64-softmmu/panda/plugins"; + if path.exists() { + return Some(path); + } + } -#[cfg(feature = "mips")] -const PLUGIN_DIR: &str = "mips-softmmu/panda/plugins"; + None + } + }) + .as_deref() +} -#[cfg(feature = "mipsel")] -const PLUGIN_DIR: &str = "mipsel-softmmu/panda/plugins"; +fn get_panda_plugin_dir() -> Option<&'static Path> { + static PANDA_PLUGIN_DIR: OnceCell> = OnceCell::new(); -#[cfg(feature = "mips64")] -const PLUGIN_DIR: &str = "mips64-softmmu/panda/plugins"; + PANDA_PLUGIN_DIR + .get_or_init(|| { + let panda_path = get_panda_path()?; -#[cfg(feature = "mips64el")] -const PLUGIN_DIR: &str = "mips64el-softmmu/panda/plugins"; + if let Ok(path) = std::env::var("PANDA_PLUGIN_DIR") { + Some(panda_path.join(path)) + } else { + let path = panda_path.join(&format!("{}/panda/plugins", ARCH_NAME)); + if path.exists() { + return Some(path); + } -#[cfg(feature = "ppc")] -const PLUGIN_DIR: &str = "ppc-softmmu/panda/plugins"; + let path = panda_path.join(&format!("{}-softmmu/panda/plugins", ARCH_NAME)); + if path.exists() { + return Some(path); + } + + let path = panda_path.join(ARCH_NAME); + if path.exists() { + return Some(path); + } + + None + } + }) + .as_deref() +} impl Plugin { pub fn new(name: &str) -> Self { - std::env::set_var( - "PANDA_DIR", - std::env::var("PANDA_PATH").expect("Missing PANDA_PATH"), - ); - let c_name = CString::new(name).unwrap(); + let panda_path = + get_panda_path().expect("PANDA_PATH not set and PANDA is not installed globally"); + unsafe { + std::env::set_var("PANDA_DIR", &panda_path); + + let c_name = CString::new(name).unwrap(); panda_require(c_name.as_ptr()); } - let path = Path::new(&std::env::var("PANDA_PATH").unwrap()) - .join(&std::env::var("PANDA_PLUGIN_DIR").unwrap_or(PLUGIN_DIR.to_owned())) + + let path = get_panda_plugin_dir() + .expect("Could not find panda plugin dir, consider setting PANDA_PLUGIN_DIR") .join(&format!("panda_{}.so", name)); + + if !path.exists() { + panic!("Could not find plugin {} at {}", name, path.display()); + } + Self { lib: libloading::Library::new(path).expect("Failed to load plugin"), }