Skip to content

Commit

Permalink
add Function::{clobbered_regs, set_clobbered_regs} methods
Browse files Browse the repository at this point in the history
  • Loading branch information
rbran committed May 13, 2024
1 parent 6f84a87 commit f964195
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 21 deletions.
15 changes: 0 additions & 15 deletions rust/src/architecture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -715,21 +715,6 @@ impl Register for CoreRegister {
}
}

impl CoreArrayProvider for CoreRegister {
type Raw = u32;
type Context = CoreArchitecture;
type Wrapped<'a> = Self;
}

unsafe impl CoreArrayProviderInner for CoreRegister {
unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
BNFreeRegisterList(raw)
}
unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
context.register_from_id(*raw).unwrap()
}
}

pub struct CoreRegisterStackInfo(*mut BNArchitecture, BNRegisterStackInfo);

impl RegisterStackInfo for CoreRegisterStackInfo {
Expand Down
56 changes: 51 additions & 5 deletions rust/src/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
use binaryninjacore_sys::*;

use crate::{
architecture::{CoreArchitecture, CoreRegister},
architecture::{Architecture, CoreArchitecture, CoreRegister, Register},
basicblock::{BasicBlock, BlockContext},
binaryview::{BinaryView, BinaryViewExt},
callingconvention::CallingConvention,
Expand All @@ -28,8 +28,8 @@ use crate::{
tags::{Tag, TagReference, TagType},
types::{
Conf, ConstantReference, HighlightColor, IndirectBranchInfo, IntegerDisplayType,
NamedTypedVariable, QualifiedName, RegisterValue, RegisterValueType,
StackVariableReference, Type, Variable,
NamedTypedVariable, QualifiedName, RegisterList, RegisterSet, RegisterValue,
RegisterValueType, StackVariableReference, Type, Variable,
},
};
use crate::{databuffer::DataBuffer, disassembly::InstructionTextToken, rc::*};
Expand Down Expand Up @@ -1034,7 +1034,11 @@ impl Function {
Conf::new(register.value.into(), register.confidence)
}

pub fn regs_read_by(&self, addr: u64, arch: Option<CoreArchitecture>) -> Array<CoreRegister> {
pub fn regs_read_by(
&self,
addr: u64,
arch: Option<CoreArchitecture>,
) -> Array<RegisterList<CoreArchitecture>> {
let arch = arch.unwrap_or_else(|| self.arch());
let mut count = 0;
let regs =
Expand All @@ -1047,7 +1051,7 @@ impl Function {
&self,
addr: u64,
arch: Option<CoreArchitecture>,
) -> Array<CoreRegister> {
) -> Array<RegisterList<CoreArchitecture>> {
let arch = arch.unwrap_or_else(|| self.arch());
let mut count = 0;
let regs =
Expand All @@ -1056,6 +1060,48 @@ impl Function {
unsafe { Array::new(regs, count, arch) }
}

pub fn set_auto_clobbered_regs<I>(&self, reg_ids: I, confidence: u8)
where
I: IntoIterator<Item = u32>,
{
let mut regs: Box<[_]> = reg_ids.into_iter().collect();
unsafe {
BNSetAutoFunctionClobberedRegisters(
self.handle,
&mut BNRegisterSetWithConfidence {
regs: regs.as_mut_ptr(),
count: regs.len(),
confidence,
},
)
}
}

/// Registers that are modified by this function
pub fn clobbered_regs(&self) -> Conf<Array<RegisterSet<CoreArchitecture>>> {
let result = unsafe { BNGetFunctionClobberedRegisters(self.handle) };

let reg_set = unsafe { Array::new(result.regs, result.count, self.arch().handle()) };
Conf::new(reg_set, result.confidence)
}

pub fn set_clobbered_regs<I>(&self, _value: I, confidence: u8)
where
I: IntoIterator<Item = CoreRegister>,
{
let mut regs: Box<[u32]> = _value.into_iter().map(|reg| reg.id()).collect();
unsafe {
BNSetUserFunctionClobberedRegisters(
self.handle,
&mut BNRegisterSetWithConfidence {
regs: regs.as_mut_ptr(),
count: regs.len(),
confidence,
},
)
}
}

pub fn stack_contents_at(
&self,
addr: u64,
Expand Down
73 changes: 72 additions & 1 deletion rust/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use crate::{

use lazy_static::lazy_static;
use std::{
borrow::Cow,
borrow::{Borrow, Cow},
collections::{HashMap, HashSet},
ffi::CStr,
fmt::{self, Debug, Display, Formatter},
Expand Down Expand Up @@ -3582,3 +3582,74 @@ unsafe impl CoreArrayProviderInner for StackVariableReference {
Guard::new(Self::from_raw(*raw), context)
}
}

/////////////////////////
// RegisterList

// NOTE only exists as an array element
pub struct RegisterList<A: Architecture> {
arch: A::Handle,
register: u32,
}

impl<A: Architecture> RegisterList<A> {
pub fn register(&self) -> A::Register {
self.arch.borrow().register_from_id(self.register).unwrap()
}
}

impl<A: Architecture> CoreArrayProvider for RegisterList<A> {
type Raw = u32;
type Context = A::Handle;
type Wrapped<'a> = Self;
}

unsafe impl<A: Architecture> CoreArrayProviderInner for RegisterList<A> {
unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
BNFreeRegisterList(raw)
}
unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
Self {
arch: context.clone(),
register: *raw,
}
}
}

/////////////////////////
// RegisterSet

// NOTE only exists as an array element
pub struct RegisterSet<A: Architecture> {
arch: A::Handle,
register: u32,
}

impl<A: Architecture> RegisterSet<A> {
pub fn register(&self) -> A::Register {
self.arch.borrow().register_from_id(self.register).unwrap()
}
}

impl<A: Architecture> CoreArrayProvider for RegisterSet<A> {
type Raw = u32;
type Context = A::Handle;
type Wrapped<'a> = Self;
}

unsafe impl<A: Architecture> CoreArrayProviderInner for RegisterSet<A> {
unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
// NOTE don't confuse this with BNFreeRegisterList
BNFreeRegisterSet(&mut BNRegisterSetWithConfidence {
regs: raw,
count,
confidence: 0,
})
}
unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
Self {
arch: context.clone(),
register: *raw,
}
}
}

0 comments on commit f964195

Please sign in to comment.