radare2 0.2.2

Rust integration helpers for radare2 core plugins
//! Minimal raw radare2 6.x C ABI used by the safe-ish wrappers.

use std::os::raw::{c_char, c_int, c_void};

/// Opaque radare2 core.
#[repr(C)]
pub struct RCore {
    _private: [u8; 0],
}

/// Opaque radare2 configuration.
#[repr(C)]
pub struct RConfig {
    _private: [u8; 0],
}

/// Identity of the binary object that native mutations target.
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct R2RustBinIdentity {
    /// Current `RBinFile` address, used only as an opaque identity token.
    pub bin_file: usize,
    /// Current `RBinObject` address, used only as an opaque identity token.
    pub bin_object: usize,
    /// Stable radare2 bin-file ID.
    pub bin_file_id: u32,
}

/// Fixed-layout native symbol request.
#[repr(C)]
pub struct R2RustSymbol {
    /// NUL-terminated original name.
    pub name: *const c_char,
    /// Physical address or `u64::MAX` when unavailable.
    pub paddr: u64,
    /// Object virtual address.
    pub vaddr: u64,
    /// Symbol size.
    pub size: u32,
    /// Stable caller-provided ordinal.
    pub ordinal: u32,
    /// [`R2_RUST_SYMBOL_NOTYPE`], [`R2_RUST_SYMBOL_OBJECT`], or
    /// [`R2_RUST_SYMBOL_FUNCTION`].
    pub kind: c_int,
}

/// Fixed-layout native address-to-source row.
#[repr(C)]
pub struct R2RustAddrLine {
    /// Analysis/runtime address.
    pub addr: u64,
    /// NUL-terminated source filename or full path.
    pub file: *const c_char,
    /// Optional NUL-terminated compilation path.
    pub path: *const c_char,
    /// One-based line.
    pub line: u32,
    /// One-based column, or zero when unknown.
    pub column: u32,
}

/// Identity of one active radare2 IO map.
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct R2RustMapIdentity {
    /// radare2 map ID.
    pub map_id: u32,
    /// Backing IO descriptor.
    pub fd: i32,
    /// IO permissions bitmask.
    pub perm: i32,
    /// Runtime virtual start.
    pub begin: u64,
    /// Map length.
    pub size: u64,
    /// Physical delta at the map start.
    pub delta: u64,
}

/// Addrline enumeration callback used by the C shim.
pub type R2RustAddrLineCallback = unsafe extern "C" fn(*mut c_void, *const R2RustAddrLine) -> bool;

/// Untyped native symbol.
pub const R2_RUST_SYMBOL_NOTYPE: c_int = 0;
/// Sized data symbol.
pub const R2_RUST_SYMBOL_OBJECT: c_int = 1;
/// Function symbol.
pub const R2_RUST_SYMBOL_FUNCTION: c_int = 2;

/// Plugin lifecycle and command session.
#[repr(C)]
pub struct RCorePluginSession {
    /// Active core.
    pub core: *mut RCore,
    /// Owning plugin descriptor.
    pub plugin: *mut c_void,
    /// Plugin-private state pointer.
    pub data: *mut c_void,
}

/// Metadata embedded in a radare2 plugin descriptor.
#[repr(C)]
pub struct RPluginMeta {
    /// Short plugin name.
    pub name: *mut c_char,
    /// One-line description.
    pub desc: *mut c_char,
    /// Author string.
    pub author: *mut c_char,
    /// Plugin version.
    pub version: *mut c_char,
    /// SPDX license identifier.
    pub license: *mut c_char,
    /// Contact string.
    pub contact: *mut c_char,
    /// Copyright string.
    pub copyright: *mut c_char,
    /// Plugin status.
    pub status: c_int,
}

/// Core-plugin callback table.
#[repr(C)]
pub struct RCorePlugin {
    /// Plugin metadata.
    pub meta: RPluginMeta,
    /// Initialization callback.
    pub init: Option<unsafe extern "C" fn(*mut RCorePluginSession) -> bool>,
    /// Finalization callback.
    pub fini: Option<unsafe extern "C" fn(*mut RCorePluginSession) -> bool>,
    /// Command callback.
    pub call: Option<unsafe extern "C" fn(*mut RCorePluginSession, *const c_char) -> bool>,
}

/// Exported descriptor radare2 reads from a plugin shared object.
#[repr(C)]
pub struct RLibStruct {
    /// Plugin class.
    pub type_: c_int,
    /// Pointer to the class-specific plugin descriptor.
    pub data: *mut c_void,
    /// radare2 version string.
    pub version: *const c_char,
    /// Optional descriptor destructor.
    pub free: Option<unsafe extern "C" fn(*mut c_void)>,
    /// Package name.
    pub pkgname: *const c_char,
    /// radare2 ABI version.
    pub abiversion: u32,
}

unsafe impl Sync for RLibStruct {}
unsafe impl Sync for RCorePlugin {}
unsafe impl Sync for RPluginMeta {}

#[link(name = "r_core")]
unsafe extern "C" {
    /// Run a command and return its status.
    pub fn r_core_cmd0(core: *mut RCore, cmd: *const c_char) -> c_int;
    /// Run a command and return a malloc-owned result string.
    pub fn r_core_cmd_str(core: *mut RCore, cmd: *const c_char) -> *mut c_char;
    /// Run newline-separated commands.
    pub fn r_core_cmd_lines(core: *mut RCore, lines: *const c_char) -> bool;
    /// Fetch a configuration string.
    pub fn r_config_get(config: *mut RConfig, name: *const c_char) -> *const c_char;
    /// Set or create a configuration string.
    pub fn r_config_set(
        config: *mut RConfig,
        name: *const c_char,
        value: *const c_char,
    ) -> *mut c_void;
    /// Fetch a configuration boolean.
    pub fn r_config_get_b(config: *mut RConfig, name: *const c_char) -> bool;
    /// Set or create a configuration boolean.
    pub fn r_config_set_b(config: *mut RConfig, name: *const c_char, value: bool) -> *mut c_void;
    /// Add a description to a configuration node.
    pub fn r_config_desc(
        config: *mut RConfig,
        name: *const c_char,
        desc: *const c_char,
    ) -> *mut c_void;
    /// Lock or unlock configuration mutation.
    pub fn r_config_lock(config: *mut RConfig, lock: bool);
    /// Find a configuration node.
    pub fn r_config_node_get(config: *mut RConfig, name: *const c_char) -> *mut c_void;

    /// Return the core configuration through the compiled radare2 headers.
    pub fn r2_rust_core_config(core: *mut RCore) -> *mut RConfig;
    /// Capture the current binary identity.
    pub fn r2_rust_current_bin_identity(core: *mut RCore, identity: *mut R2RustBinIdentity)
    -> bool;
    /// Check that a captured binary identity is still current.
    pub fn r2_rust_bin_identity_matches(
        core: *mut RCore,
        identity: *const R2RustBinIdentity,
    ) -> bool;
    /// Return the current native symbol-vector length, or `usize::MAX` on failure.
    pub fn r2_rust_symbol_count(core: *mut RCore, identity: *const R2RustBinIdentity) -> usize;
    /// Test whether an exact native symbol already exists.
    pub fn r2_rust_symbol_exists(
        core: *mut RCore,
        identity: *const R2RustBinIdentity,
        symbol: *const R2RustSymbol,
    ) -> bool;
    /// Append one owned native symbol.
    pub fn r2_rust_symbol_add(
        core: *mut RCore,
        identity: *const R2RustBinIdentity,
        symbol: *const R2RustSymbol,
    ) -> bool;
    /// Remove all native symbols after `length`.
    pub fn r2_rust_symbols_truncate(
        core: *mut RCore,
        identity: *const R2RustBinIdentity,
        length: usize,
    ) -> bool;
    /// Enumerate address-to-source rows in insertion order.
    pub fn r2_rust_addrline_foreach(
        core: *mut RCore,
        identity: *const R2RustBinIdentity,
        callback: R2RustAddrLineCallback,
        user: *mut c_void,
    ) -> bool;
    /// Reset the complete current addrline store.
    pub fn r2_rust_addrline_reset(core: *mut RCore, identity: *const R2RustBinIdentity) -> bool;
    /// Add one address-to-source row, copying its strings into radare2.
    pub fn r2_rust_addrline_add(
        core: *mut RCore,
        identity: *const R2RustBinIdentity,
        line: *const R2RustAddrLine,
    ) -> bool;
    /// Resolve a physical address through the active IO map.
    pub fn r2_rust_map_for_paddr(
        core: *mut RCore,
        paddr: u64,
        vaddr: *mut u64,
        identity: *mut R2RustMapIdentity,
    ) -> bool;
    /// Resolve and validate a virtual address through the active IO map.
    pub fn r2_rust_map_for_vaddr(
        core: *mut RCore,
        vaddr: u64,
        paddr: *mut u64,
        identity: *mut R2RustMapIdentity,
    ) -> bool;
    /// Check that an IO map has not changed.
    pub fn r2_rust_map_identity_matches(
        core: *mut RCore,
        identity: *const R2RustMapIdentity,
    ) -> bool;
    /// Test whether an analyzed function starts at `addr`.
    pub fn r2_rust_function_exists(core: *mut RCore, addr: u64) -> bool;
    /// Analyze and name a new function at `addr`.
    pub fn r2_rust_function_analyze(core: *mut RCore, addr: u64, name: *const c_char) -> bool;
    /// Check that an analyzed function still has the expected identity.
    pub fn r2_rust_function_matches(core: *mut RCore, addr: u64, name: *const c_char) -> bool;
    /// Delete an exact plugin-owned analyzed function.
    pub fn r2_rust_function_delete(core: *mut RCore, addr: u64, name: *const c_char) -> bool;
    /// Test whether an exact xref exists.
    pub fn r2_rust_xref_exists(core: *mut RCore, from: u64, to: u64, type_: c_int) -> bool;
    /// Insert an exact xref when absent.
    pub fn r2_rust_xref_add(core: *mut RCore, from: u64, to: u64, type_: c_int) -> bool;
    /// Delete an exact xref when its type still matches.
    pub fn r2_rust_xref_delete(core: *mut RCore, from: u64, to: u64, type_: c_int) -> bool;
}

unsafe extern "C" {
    /// Free memory allocated by radare2/libc.
    pub fn free(ptr: *mut c_void);
}