diff options
Diffstat (limited to 'rust/src/basicblock.rs')
| -rw-r--r-- | rust/src/basicblock.rs | 310 |
1 files changed, 0 insertions, 310 deletions
diff --git a/rust/src/basicblock.rs b/rust/src/basicblock.rs deleted file mode 100644 index a6ac8f74..00000000 --- a/rust/src/basicblock.rs +++ /dev/null @@ -1,310 +0,0 @@ -// Copyright 2021-2024 Vector 35 Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use std::fmt; - -use crate::architecture::CoreArchitecture; -use crate::function::Function; -use binaryninjacore_sys::*; - -use crate::rc::*; - -enum EdgeDirection { - Incoming, - Outgoing, -} - -pub struct Edge<'a, C: 'a + BlockContext> { - branch: super::BranchType, - back_edge: bool, - source: Guard<'a, BasicBlock<C>>, - target: Guard<'a, BasicBlock<C>>, -} - -impl<'a, C: 'a + BlockContext> Edge<'a, C> { - pub fn branch_type(&self) -> super::BranchType { - self.branch - } - - pub fn back_edge(&self) -> bool { - self.back_edge - } - - pub fn source(&self) -> &BasicBlock<C> { - &self.source - } - - pub fn target(&self) -> &BasicBlock<C> { - &self.target - } -} - -impl<'a, C: 'a + fmt::Debug + BlockContext> fmt::Debug for Edge<'a, C> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "{:?} ({}) {:?} -> {:?}", - self.branch, self.back_edge, &*self.source, &*self.target - ) - } -} - -pub struct EdgeContext<'a, C: 'a + BlockContext> { - dir: EdgeDirection, - orig_block: &'a BasicBlock<C>, -} - -impl<'a, C: 'a + BlockContext> CoreArrayProvider for Edge<'a, C> { - type Raw = BNBasicBlockEdge; - type Context = EdgeContext<'a, C>; - type Wrapped<'b> = Edge<'b, C> where 'a: 'b; -} - -unsafe impl<'a, C: 'a + BlockContext> CoreArrayProviderInner for Edge<'a, C> { - unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) { - BNFreeBasicBlockEdgeList(raw, count); - } - unsafe fn wrap_raw<'b>(raw: &'b Self::Raw, context: &'b Self::Context) -> Self::Wrapped<'b> { - let edge_target = Guard::new( - BasicBlock::from_raw(raw.target, context.orig_block.context.clone()), - raw, - ); - let orig_block = Guard::new( - BasicBlock::from_raw( - context.orig_block.handle, - context.orig_block.context.clone(), - ), - raw, - ); - - let (source, target) = match context.dir { - EdgeDirection::Incoming => (edge_target, orig_block), - EdgeDirection::Outgoing => (orig_block, edge_target), - }; - - Edge { - branch: raw.type_, - back_edge: raw.backEdge, - source, - target, - } - } -} - -pub trait BlockContext: Clone + Sync + Send + Sized { - type Instruction; - type Iter: Iterator<Item = Self::Instruction>; - - fn start(&self, block: &BasicBlock<Self>) -> Self::Instruction; - fn iter(&self, block: &BasicBlock<Self>) -> Self::Iter; -} - -#[derive(PartialEq, Eq, Hash)] -pub struct BasicBlock<C: BlockContext> { - pub(crate) handle: *mut BNBasicBlock, - context: C, -} - -unsafe impl<C: BlockContext> Send for BasicBlock<C> {} -unsafe impl<C: BlockContext> Sync for BasicBlock<C> {} - -impl<C: BlockContext> BasicBlock<C> { - pub(crate) unsafe fn from_raw(handle: *mut BNBasicBlock, context: C) -> Self { - Self { handle, context } - } - - // TODO native bb vs il bbs - pub fn function(&self) -> Ref<Function> { - unsafe { - let func = BNGetBasicBlockFunction(self.handle); - Function::from_raw(func) - } - } - - pub fn arch(&self) -> CoreArchitecture { - unsafe { - let arch = BNGetBasicBlockArchitecture(self.handle); - CoreArchitecture::from_raw(arch) - } - } - - pub fn iter(&self) -> C::Iter { - self.context.iter(self) - } - - pub fn raw_start(&self) -> u64 { - unsafe { BNGetBasicBlockStart(self.handle) } - } - - pub fn raw_end(&self) -> u64 { - unsafe { BNGetBasicBlockEnd(self.handle) } - } - - pub fn raw_length(&self) -> u64 { - unsafe { BNGetBasicBlockLength(self.handle) } - } - - pub fn incoming_edges(&self) -> Array<Edge<C>> { - unsafe { - let mut count = 0; - let edges = BNGetBasicBlockIncomingEdges(self.handle, &mut count); - - Array::new( - edges, - count, - EdgeContext { - dir: EdgeDirection::Incoming, - orig_block: self, - }, - ) - } - } - - pub fn outgoing_edges(&self) -> Array<Edge<C>> { - unsafe { - let mut count = 0; - let edges = BNGetBasicBlockOutgoingEdges(self.handle, &mut count); - - Array::new( - edges, - count, - EdgeContext { - dir: EdgeDirection::Outgoing, - orig_block: self, - }, - ) - } - } - - // is this valid for il blocks? - pub fn has_undetermined_outgoing_edges(&self) -> bool { - unsafe { BNBasicBlockHasUndeterminedOutgoingEdges(self.handle) } - } - - pub fn can_exit(&self) -> bool { - unsafe { BNBasicBlockCanExit(self.handle) } - } - - pub fn index(&self) -> usize { - unsafe { BNGetBasicBlockIndex(self.handle) } - } - - pub fn immediate_dominator(&self) -> Option<Ref<Self>> { - unsafe { - let block = BNGetBasicBlockImmediateDominator(self.handle, false); - - if block.is_null() { - return None; - } - - Some(Ref::new(BasicBlock::from_raw(block, self.context.clone()))) - } - } - - pub fn dominators(&self) -> Array<BasicBlock<C>> { - unsafe { - let mut count = 0; - let blocks = BNGetBasicBlockDominators(self.handle, &mut count, false); - - Array::new(blocks, count, self.context.clone()) - } - } - - pub fn strict_dominators(&self) -> Array<BasicBlock<C>> { - unsafe { - let mut count = 0; - let blocks = BNGetBasicBlockStrictDominators(self.handle, &mut count, false); - - Array::new(blocks, count, self.context.clone()) - } - } - - pub fn dominator_tree_children(&self) -> Array<BasicBlock<C>> { - unsafe { - let mut count = 0; - let blocks = BNGetBasicBlockDominatorTreeChildren(self.handle, &mut count, false); - - Array::new(blocks, count, self.context.clone()) - } - } - - pub fn dominance_frontier(&self) -> Array<BasicBlock<C>> { - unsafe { - let mut count = 0; - let blocks = BNGetBasicBlockDominanceFrontier(self.handle, &mut count, false); - - Array::new(blocks, count, self.context.clone()) - } - } - - // TODO iterated dominance frontier -} - -impl<'a, C: BlockContext> IntoIterator for &'a BasicBlock<C> { - type Item = C::Instruction; - type IntoIter = C::Iter; - - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -impl<C: fmt::Debug + BlockContext> fmt::Debug for BasicBlock<C> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "<bb handle {:p} context {:?} contents: {} -> {}>", - self.handle, - &self.context, - self.raw_start(), - self.raw_end() - ) - } -} - -impl<C: BlockContext> ToOwned for BasicBlock<C> { - type Owned = Ref<Self>; - - fn to_owned(&self) -> Self::Owned { - unsafe { RefCountable::inc_ref(self) } - } -} - -unsafe impl<C: BlockContext> RefCountable for BasicBlock<C> { - unsafe fn inc_ref(handle: &Self) -> Ref<Self> { - Ref::new(Self { - handle: BNNewBasicBlockReference(handle.handle), - context: handle.context.clone(), - }) - } - - unsafe fn dec_ref(handle: &Self) { - BNFreeBasicBlock(handle.handle); - } -} - -impl<C: BlockContext> CoreArrayProvider for BasicBlock<C> { - type Raw = *mut BNBasicBlock; - type Context = C; - type Wrapped<'a> = Guard<'a, BasicBlock<C>> where C: 'a; -} - -unsafe impl<C: BlockContext> CoreArrayProviderInner for BasicBlock<C> { - unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) { - BNFreeBasicBlockList(raw, count); - } - unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> { - Guard::new(BasicBlock::from_raw(*raw, context.clone()), context) - } -} |
