falcon/il/function.rs
1//! A `Function` holds a `ControlFlowGraph`.
2//!
3//! We can think of a `Function` as providing _location_ to a `ControlFlowGraph`.
4
5use crate::il::*;
6use crate::Error;
7use serde::{Deserialize, Serialize};
8
9/// A function for Falcon IL. Provides location and context in a `Program` to a
10/// `ControlFlowGraph`.
11#[derive(Clone, Debug, Deserialize, Hash, Eq, PartialEq, Serialize)]
12pub struct Function {
13    // The address where this function was found
14    address: u64,
15    // The `ControlFlowGraph` capturing semantics of the function
16    control_flow_graph: ControlFlowGraph,
17    // The name of the function
18    name: Option<String>,
19    // Functions which belong to Programs have indices
20    index: Option<usize>,
21}
22
23impl Function {
24    /// Create a new `Function`
25    ///
26    /// # Parameters
27    /// * `address` - The address where we recovered this function.
28    /// * `control_flow_graph` - A `ControlFlowGraph` capturing the semantics of this function.
29    pub fn new(address: u64, control_flow_graph: ControlFlowGraph) -> Function {
30        Function {
31            address,
32            control_flow_graph,
33            name: None,
34            index: None,
35        }
36    }
37
38    /// Create a Vec of every RefFunctionLocation for this function.
39    ///
40    /// Convenient for analyses where we need to check every location in a
41    /// function
42    pub fn locations(&self) -> Vec<RefFunctionLocation> {
43        let mut locations = Vec::new();
44
45        for block in self.blocks() {
46            let instructions = block.instructions();
47            if instructions.is_empty() {
48                locations.push(RefFunctionLocation::EmptyBlock(block));
49            } else {
50                for instruction in instructions {
51                    locations.push(RefFunctionLocation::Instruction(block, instruction));
52                }
53            }
54        }
55
56        for edge in self.edges() {
57            locations.push(RefFunctionLocation::Edge(edge))
58        }
59
60        locations
61    }
62
63    /// Get the address of this `Function`.
64    ///
65    /// The address returned will be the address set when this `Function` was created,
66    /// which should be the virtual address where this `Function` was found.
67    pub fn address(&self) -> u64 {
68        self.address
69    }
70
71    /// Return a `Block` from this `Function`'s `ControlFlowGraph` by index.
72    pub fn block(&self, index: usize) -> Result<&Block, Error> {
73        self.control_flow_graph.block(index)
74    }
75
76    /// Return a mutable reference to a `Block` in this `Function`
77    pub fn block_mut(&mut self, index: usize) -> Result<&mut Block, Error> {
78        self.control_flow_graph.block_mut(index)
79    }
80
81    /// Return a Vec of all `Block` in this `Function`
82    pub fn blocks(&self) -> Vec<&Block> {
83        self.control_flow_graph.blocks()
84    }
85
86    /// Return a Vec of mutable references to all `Block` in this `Function`
87    pub fn blocks_mut(&mut self) -> Vec<&mut Block> {
88        self.control_flow_graph.blocks_mut()
89    }
90
91    /// Return an `Edge` from this `Function`'s `ControlFlowGraph` by index.
92    pub fn edge(&self, head: usize, tail: usize) -> Result<&Edge, Error> {
93        self.control_flow_graph.edge(head, tail)
94    }
95
96    /// Return a vec of all `Edge` in this `Function`
97    pub fn edges(&self) -> Vec<&Edge> {
98        self.control_flow_graph.edges()
99    }
100
101    /// Return the `ControlFlowGraph` for this `Function`.
102    pub fn control_flow_graph(&self) -> &ControlFlowGraph {
103        &self.control_flow_graph
104    }
105
106    /// Return a mutable reference to the `ControlFlowGraph` for this `Function`.
107    pub fn control_flow_graph_mut(&mut self) -> &mut ControlFlowGraph {
108        &mut self.control_flow_graph
109    }
110
111    /// Return the name of this `Function`.
112    pub fn name(&self) -> String {
113        match self.name {
114            Some(ref name) => name.to_string(),
115            None => format!("unknown@{:08X}", self.address),
116        }
117    }
118
119    /// Set this `Function`'s name.
120    pub fn set_name(&mut self, name: Option<String>) {
121        self.name = name;
122    }
123
124    /// Return the index of this `Function`. A `Function` will have an index if
125    /// it is added to a `Program`.
126    pub fn index(&self) -> Option<usize> {
127        self.index
128    }
129
130    pub fn set_index(&mut self, index: Option<usize>) {
131        self.index = index;
132    }
133}