vtil_parser/
instr_builder.rs

1// BSD 3-Clause License
2//
3// Copyright © 2021 Keegan Saunders
4// Copyright © 2021 VTIL Project
5// All rights reserved.
6//
7// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions are met:
9//
10// 1. Redistributions of source code must retain the above copyright notice, this
11//    list of conditions and the following disclaimer.
12//
13// 2. Redistributions in binary form must reproduce the above copyright notice,
14//    this list of conditions and the following disclaimer in the documentation
15//    and/or other materials provided with the distribution.
16//
17// 3. Neither the name of the copyright holder nor the names of its
18//    contributors may be used to endorse or promote products derived from
19//    this software without specific prior written permission.
20//
21// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31//
32
33use crate::{
34    BasicBlock, ImmediateDesc, Instruction, Op, Operand, RegisterDesc, RegisterFlags, Vip,
35};
36use std::convert::TryInto;
37
38const VTIL_ARCH_POPPUSH_ENFORCED_STACK_ALIGN: usize = 2;
39
40/// Builder for VTIL instructions in an associated [`BasicBlock`]
41pub struct InstructionBuilder<'a> {
42    /// Insertion point, *must* be cleared after use
43    pub vip: Vip,
44    /// The current [`BasicBlock`]
45    pub basic_block: &'a mut BasicBlock,
46}
47
48// Helper for inserting instructions with no associated metadata
49fn insert_instr(builder: &mut InstructionBuilder, op: Op) {
50    let vip = if builder.vip != Vip::invalid() {
51        let vip = builder.vip;
52        builder.vip = Vip::invalid();
53        vip
54    } else {
55        builder.vip
56    };
57
58    let sp_offset = builder.basic_block.sp_offset;
59    let sp_index = builder.basic_block.sp_index;
60
61    builder.basic_block.instructions.push(Instruction {
62        op,
63        vip,
64        sp_offset,
65        sp_index,
66        sp_reset: false,
67    });
68}
69
70impl<'a> InstructionBuilder<'a> {
71    /// Build an [`InstructionBuilder`] from an existing [`BasicBlock`]
72    pub fn from(basic_block: &'a mut BasicBlock) -> InstructionBuilder<'a> {
73        InstructionBuilder {
74            vip: Vip::invalid(),
75            basic_block,
76        }
77    }
78
79    /// Queues a stack shift
80    pub fn shift_sp(&mut self, offset: i64) {
81        self.basic_block.sp_offset += offset;
82    }
83
84    /// Pushes an operand up the stack queueing the shift in the stack pointer
85    pub fn push(&mut self, op1: Operand) -> &mut Self {
86        if let Operand::RegisterDesc(sp) = op1 {
87            if sp.flags.contains(RegisterFlags::STACK_POINTER) {
88                let tmp0 = self.basic_block.tmp(64);
89                self.mov(tmp0, op1).push(tmp0.into());
90                return self;
91            }
92        }
93
94        let misalignment = (op1.size() % VTIL_ARCH_POPPUSH_ENFORCED_STACK_ALIGN) as i64;
95        if misalignment != 0 {
96            let padding_size = VTIL_ARCH_POPPUSH_ENFORCED_STACK_ALIGN as i64 - misalignment;
97            self.shift_sp(-padding_size);
98            self.str(
99                RegisterDesc::SP,
100                self.basic_block.sp_offset.into(),
101                ImmediateDesc::new(0u64, TryInto::<u32>::try_into(padding_size).unwrap() * 8)
102                    .into(),
103            );
104        }
105
106        self.shift_sp(-(op1.size() as i64));
107        self.str(RegisterDesc::SP, self.basic_block.sp_offset.into(), op1);
108
109        self
110    }
111
112    /// Pops an operand from the stack queueing the shift in the stack pointer
113    pub fn pop(&mut self, op1: RegisterDesc) -> &mut Self {
114        let offset = self.basic_block.sp_offset;
115
116        let misalignment = (op1.size() % VTIL_ARCH_POPPUSH_ENFORCED_STACK_ALIGN) as i64;
117        if misalignment != 0 {
118            self.shift_sp(VTIL_ARCH_POPPUSH_ENFORCED_STACK_ALIGN as i64 - misalignment);
119        }
120
121        self.shift_sp(op1.size() as i64);
122        self.ldd(op1, RegisterDesc::SP, offset.into());
123
124        self
125    }
126
127    /// Push flags register
128    pub fn pushf(&mut self) -> &mut Self {
129        self.push(RegisterDesc::FLAGS.into())
130    }
131
132    /// Pop flags register
133    pub fn popf(&mut self) -> &mut Self {
134        self.push(RegisterDesc::FLAGS.into())
135    }
136
137    /// Insert an [`Op::Mov`]
138    pub fn mov(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
139        insert_instr(self, Op::Mov(op1.into(), op2.into()));
140        self
141    }
142
143    /// Insert an [`Op::Movsx`]
144    pub fn movsx(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
145        insert_instr(self, Op::Movsx(op1.into(), op2.into()));
146        self
147    }
148
149    /// Insert an [`Op::Str`]
150    pub fn str(&mut self, op1: RegisterDesc, op2: ImmediateDesc, op3: Operand) -> &mut Self {
151        insert_instr(self, Op::Str(op1.into(), op2.into(), op3.into()));
152        self
153    }
154
155    /// Insert an [`Op::Ldd`]
156    pub fn ldd(&mut self, op1: RegisterDesc, op2: RegisterDesc, op3: ImmediateDesc) -> &mut Self {
157        insert_instr(self, Op::Ldd(op1.into(), op2.into(), op3.into()));
158        self
159    }
160
161    /// Insert an [`Op::Neg`]
162    pub fn neg(&mut self, op1: RegisterDesc) -> &mut Self {
163        insert_instr(self, Op::Neg(op1.into()));
164        self
165    }
166
167    /// Insert an [`Op::Add`]
168    pub fn add(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
169        insert_instr(self, Op::Add(op1.into(), op2.into()));
170        self
171    }
172
173    /// Insert an [`Op::Sub`]
174    pub fn sub(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
175        insert_instr(self, Op::Sub(op1.into(), op2.into()));
176        self
177    }
178
179    /// Insert an [`Op::Mul`]
180    pub fn mul(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
181        insert_instr(self, Op::Mul(op1.into(), op2.into()));
182        self
183    }
184
185    /// Insert an [`Op::Mulhi`]
186    pub fn mulhi(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
187        insert_instr(self, Op::Mulhi(op1.into(), op2.into()));
188        self
189    }
190
191    /// Insert an [`Op::Imul`]
192    pub fn imul(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
193        insert_instr(self, Op::Imul(op1.into(), op2.into()));
194        self
195    }
196
197    /// Insert an [`Op::Imulhi`]
198    pub fn imulhi(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
199        insert_instr(self, Op::Imulhi(op1.into(), op2.into()));
200        self
201    }
202
203    /// Insert an [`Op::Div`]
204    pub fn div(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
205        insert_instr(self, Op::Div(op1.into(), op2.into(), op3.into()));
206        self
207    }
208
209    /// Insert an [`Op::Rem`]
210    pub fn rem(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
211        insert_instr(self, Op::Rem(op1.into(), op2.into(), op3.into()));
212        self
213    }
214
215    /// Insert an [`Op::Idiv`]
216    pub fn idiv(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
217        insert_instr(self, Op::Idiv(op1.into(), op2.into(), op3.into()));
218        self
219    }
220
221    /// Insert an [`Op::Irem`]
222    pub fn irem(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
223        insert_instr(self, Op::Irem(op1.into(), op2.into(), op3.into()));
224        self
225    }
226
227    /// Insert an [`Op::Popcnt`]
228    pub fn popcnt(&mut self, op1: RegisterDesc) -> &mut Self {
229        insert_instr(self, Op::Popcnt(op1.into()));
230        self
231    }
232
233    /// Insert an [`Op::Bsf`]
234    pub fn bsf(&mut self, op1: RegisterDesc) -> &mut Self {
235        insert_instr(self, Op::Bsf(op1.into()));
236        self
237    }
238
239    /// Insert an [`Op::Bsr`]
240    pub fn bsr(&mut self, op1: RegisterDesc) -> &mut Self {
241        insert_instr(self, Op::Bsr(op1.into()));
242        self
243    }
244
245    /// Insert an [`Op::Not`]
246    pub fn not(&mut self, op1: RegisterDesc) -> &mut Self {
247        insert_instr(self, Op::Not(op1.into()));
248        self
249    }
250
251    /// Insert an [`Op::Shr`]
252    pub fn shr(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
253        insert_instr(self, Op::Shr(op1.into(), op2.into()));
254        self
255    }
256
257    /// Insert an [`Op::Shl`]
258    pub fn shl(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
259        insert_instr(self, Op::Shl(op1.into(), op2.into()));
260        self
261    }
262
263    /// Insert an [`Op::Xor`]
264    pub fn xor(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
265        insert_instr(self, Op::Xor(op1.into(), op2.into()));
266        self
267    }
268
269    /// Insert an [`Op::Or`]
270    pub fn or(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
271        insert_instr(self, Op::Or(op1.into(), op2.into()));
272        self
273    }
274
275    /// Insert an [`Op::And`]
276    pub fn and(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
277        insert_instr(self, Op::And(op1.into(), op2.into()));
278        self
279    }
280
281    /// Insert an [`Op::Ror`]
282    pub fn ror(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
283        insert_instr(self, Op::Ror(op1.into(), op2.into()));
284        self
285    }
286
287    /// Insert an [`Op::Rol`]
288    pub fn rol(&mut self, op1: RegisterDesc, op2: Operand) -> &mut Self {
289        insert_instr(self, Op::Rol(op1.into(), op2.into()));
290        self
291    }
292
293    /// Insert an [`Op::Tg`]
294    pub fn tg(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
295        insert_instr(self, Op::Tg(op1.into(), op2.into(), op3.into()));
296        self
297    }
298
299    /// Insert an [`Op::Tge`]
300    pub fn tge(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
301        insert_instr(self, Op::Tge(op1.into(), op2.into(), op3.into()));
302        self
303    }
304
305    /// Insert an [`Op::Te`]
306    pub fn te(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
307        insert_instr(self, Op::Te(op1.into(), op2.into(), op3.into()));
308        self
309    }
310
311    /// Insert an [`Op::Tne`]
312    pub fn tne(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
313        insert_instr(self, Op::Tne(op1.into(), op2.into(), op3.into()));
314        self
315    }
316
317    /// Insert an [`Op::Tl`]
318    pub fn tl(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
319        insert_instr(self, Op::Tl(op1.into(), op2.into(), op3.into()));
320        self
321    }
322
323    /// Insert an [`Op::Tle`]
324    pub fn tle(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
325        insert_instr(self, Op::Tle(op1.into(), op2.into(), op3.into()));
326        self
327    }
328
329    /// Insert an [`Op::Tug`]
330    pub fn tug(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
331        insert_instr(self, Op::Tug(op1.into(), op2.into(), op3.into()));
332        self
333    }
334
335    /// Insert an [`Op::Tuge`]
336    pub fn tuge(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
337        insert_instr(self, Op::Tuge(op1.into(), op2.into(), op3.into()));
338        self
339    }
340
341    /// Insert an [`Op::Tul`]
342    pub fn tul(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
343        insert_instr(self, Op::Tul(op1.into(), op2.into(), op3.into()));
344        self
345    }
346
347    /// Insert an [`Op::Tule`]
348    pub fn tule(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
349        insert_instr(self, Op::Tule(op1.into(), op2.into(), op3.into()));
350        self
351    }
352
353    /// Insert an [`Op::Ifs`]
354    pub fn ifs(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
355        insert_instr(self, Op::Ifs(op1.into(), op2.into(), op3.into()));
356        self
357    }
358
359    /// Insert an [`Op::Js`]
360    pub fn js(&mut self, op1: RegisterDesc, op2: Operand, op3: Operand) -> &mut Self {
361        insert_instr(self, Op::Js(op1.into(), op2.into(), op3.into()));
362        self
363    }
364
365    /// Insert an [`Op::Jmp`]
366    pub fn jmp(&mut self, op1: Operand) -> &mut Self {
367        insert_instr(self, Op::Jmp(op1.into()));
368        self
369    }
370
371    /// Insert an [`Op::Vexit`]
372    pub fn vexit(&mut self, op1: Operand) -> &mut Self {
373        insert_instr(self, Op::Vexit(op1.into()));
374        self
375    }
376
377    /// Insert an [`Op::Vxcall`]
378    pub fn vxcall(&mut self, op1: Operand) -> &mut Self {
379        insert_instr(self, Op::Vxcall(op1.into()));
380        self
381    }
382
383    /// Insert an [`Op::Nop`]
384    pub fn nop(&mut self) -> &mut Self {
385        insert_instr(self, Op::Nop);
386        self
387    }
388
389    /// Insert an [`Op::Sfence`]
390    pub fn sfence(&mut self) -> &mut Self {
391        insert_instr(self, Op::Sfence);
392        self
393    }
394
395    /// Insert an [`Op::Lfence`]
396    pub fn lfence(&mut self) -> &mut Self {
397        insert_instr(self, Op::Lfence);
398        self
399    }
400
401    /// Insert an [`Op::Vemit`]
402    pub fn vemit(&mut self, op1: ImmediateDesc) -> &mut Self {
403        insert_instr(self, Op::Vemit(op1.into()));
404        self
405    }
406
407    /// Insert an [`Op::Vpinr`]
408    pub fn vpinr(&mut self, op1: RegisterDesc) -> &mut Self {
409        insert_instr(self, Op::Vpinr(op1.into()));
410        self
411    }
412
413    /// Insert an [`Op::Vpinw`]
414    pub fn vpinw(&mut self, op1: RegisterDesc) -> &mut Self {
415        insert_instr(self, Op::Vpinw(op1.into()));
416        self
417    }
418
419    /// Insert an [`Op::Vpinrm`]
420    pub fn vpinrm(
421        &mut self,
422        op1: RegisterDesc,
423        op2: ImmediateDesc,
424        op3: ImmediateDesc,
425    ) -> &mut Self {
426        insert_instr(self, Op::Vpinrm(op1.into(), op2.into(), op3.into()));
427        self
428    }
429
430    /// Insert an [`Op::Vpinwm`]
431    pub fn vpinwm(
432        &mut self,
433        op1: RegisterDesc,
434        op2: ImmediateDesc,
435        op3: ImmediateDesc,
436    ) -> &mut Self {
437        insert_instr(self, Op::Vpinwm(op1.into(), op2.into(), op3.into()));
438        self
439    }
440}
441
442#[cfg(test)]
443mod test {
444    #[test]
445    fn basic() {
446        use crate::*;
447
448        let mut routine = Routine::new(ArchitectureIdentifier::Virtual);
449        let basic_block = routine.create_block(Vip(0)).unwrap();
450        let tmp0 = basic_block.tmp(64);
451        let mut builder = InstructionBuilder::from(basic_block);
452        builder.mov(tmp0, 0xA57E6F0335298D0u64.into());
453
454        assert_eq!(basic_block.instructions.len(), 1);
455        let instr = &basic_block.instructions[0];
456        assert!(matches!(instr.op, Op::Mov(_, _)));
457    }
458}