retour\pic/
emitter.rs

1use super::Thunkable;
2
3/// An interface for generating PIC.
4pub struct CodeEmitter {
5  thunks: Vec<Box<dyn Thunkable>>,
6}
7
8/// Used for combining PIC segments.
9impl CodeEmitter {
10  /// Constructs a new code emitter.
11  pub fn new() -> Self {
12    CodeEmitter { thunks: Vec::new() }
13  }
14
15  /// Generates code for use at the specified address.
16  pub fn emit(&self, base: *const ()) -> Vec<u8> {
17    let mut result = Vec::with_capacity(self.len());
18    let mut base = base as usize;
19
20    for thunk in &self.thunks {
21      // Retrieve the code for the segment
22      let code = thunk.generate(base);
23      assert_eq!(code.len(), thunk.len());
24
25      // Advance the current EIP address
26      base += thunk.len();
27      result.extend(code);
28    }
29
30    result
31  }
32
33  /// Adds a position-independant code segment.
34  pub fn add_thunk(&mut self, thunk: Box<dyn Thunkable>) {
35    self.thunks.push(thunk);
36  }
37
38  /// Returns the total size of a all code segments.
39  pub fn len(&self) -> usize {
40    self.thunks.iter().fold(0, |sum, thunk| sum + thunk.len())
41  }
42}