Commit babf80f5 by Enkelmann Committed by Enkelmann

Handle special cases in BAP IR to internal IR conversion.

parent 53193734
...@@ -239,9 +239,15 @@ impl From<Expression> for IrExpression { ...@@ -239,9 +239,15 @@ impl From<Expression> for IrExpression {
match expr { match expr {
Var(var) => IrExpression::Var(var.into()), Var(var) => IrExpression::Var(var.into()),
Const(bitvector) => IrExpression::Const(bitvector), Const(bitvector) => IrExpression::Const(bitvector),
Load { .. } | Store { .. } | Let { .. } | Unknown { .. } | IfThenElse { .. } => { Load { .. } | Store { .. } | Let { .. } => panic!(),
panic!() IfThenElse { true_exp, .. } => IrExpression::Unknown {
} description: "BAP-IfThenElse-expression".into(),
size: true_exp.bitsize().into(),
},
Unknown { description, type_ } => IrExpression::Unknown {
description,
size: type_.bitsize().unwrap().into(),
},
BinOp { op, lhs, rhs } => IrExpression::BinOp { BinOp { op, lhs, rhs } => IrExpression::BinOp {
op: op.into(), op: op.into(),
lhs: Box::new(IrExpression::from(*lhs)), lhs: Box::new(IrExpression::from(*lhs)),
...@@ -254,41 +260,78 @@ impl From<Expression> for IrExpression { ...@@ -254,41 +260,78 @@ impl From<Expression> for IrExpression {
Cast { kind, width, arg } => { Cast { kind, width, arg } => {
use CastType::*; use CastType::*;
match kind { match kind {
UNSIGNED => IrExpression::Cast { UNSIGNED => {
arg: Box::new(IrExpression::from(*arg)), assert!(width % 8 == 0);
op: IrCastOpType::IntZExt, IrExpression::Cast {
size: width.into(), arg: Box::new(IrExpression::from(*arg)),
}, op: IrCastOpType::IntZExt,
SIGNED => IrExpression::Cast { size: width.into(),
arg: Box::new(IrExpression::from(*arg)), }
op: IrCastOpType::IntSExt, }
size: width.into(), SIGNED => {
},
HIGH => {
assert!(width % 8 == 0); assert!(width % 8 == 0);
let low_byte = (arg.bitsize() - width).into(); IrExpression::Cast {
IrExpression::Subpiece {
arg: Box::new(IrExpression::from(*arg)), arg: Box::new(IrExpression::from(*arg)),
low_byte, op: IrCastOpType::IntSExt,
size: width.into(), size: width.into(),
} }
} }
LOW => IrExpression::Subpiece { HIGH => {
arg: Box::new(IrExpression::from(*arg)), if width == 1 {
low_byte: (0 as u64).into(), IrExpression::BinOp {
size: width.into(), op: IrBinOpType::IntSLess,
}, lhs: Box::new(IrExpression::Const(Bitvector::zero(
(arg.bitsize() as usize).into(),
))),
rhs: Box::new(IrExpression::from(*arg)),
}
} else {
assert!(width % 8 == 0);
let low_byte = (arg.bitsize() - width).into();
IrExpression::Subpiece {
arg: Box::new(IrExpression::from(*arg)),
low_byte,
size: width.into(),
}
}
}
LOW => {
if width == 1 {
IrExpression::Subpiece {
low_byte: ByteSize::new(0),
size: ByteSize::new(1),
arg: Box::new(IrExpression::BinOp {
op: IrBinOpType::IntAnd,
lhs: Box::new(IrExpression::Const(Bitvector::one(
(arg.bitsize() as usize).into(),
))),
rhs: Box::new(IrExpression::from(*arg)),
}),
}
} else {
assert!(width % 8 == 0);
IrExpression::Subpiece {
arg: Box::new(IrExpression::from(*arg)),
low_byte: (0 as u64).into(),
size: width.into(),
}
}
}
} }
} }
Extract { Extract {
low_bit, low_bit,
high_bit, high_bit,
arg, arg,
} => IrExpression::Subpiece { } => {
size: (high_bit - low_bit + 1).into(), assert!(low_bit % 8 == 0);
low_byte: low_bit.into(), assert!((high_bit + 1) % 8 == 0);
arg: Box::new(IrExpression::from(*arg)), IrExpression::Subpiece {
}, size: (high_bit - low_bit + 1).into(),
low_byte: low_bit.into(),
arg: Box::new(IrExpression::from(*arg)),
}
}
Concat { left, right } => IrExpression::BinOp { Concat { left, right } => IrExpression::BinOp {
op: IrBinOpType::Piece, op: IrBinOpType::Piece,
lhs: Box::new(IrExpression::from(*left)), lhs: Box::new(IrExpression::from(*left)),
......
...@@ -60,6 +60,12 @@ impl From<ByteSize> for apint::BitWidth { ...@@ -60,6 +60,12 @@ impl From<ByteSize> for apint::BitWidth {
} }
} }
impl ByteSize {
pub fn new(value: u64) -> ByteSize {
ByteSize(value)
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
......
...@@ -58,10 +58,8 @@ impl Def { ...@@ -58,10 +58,8 @@ impl Def {
match self.rhs { match self.rhs {
Expression::Load { address, .. } => { Expression::Load { address, .. } => {
let (defs, cleaned_address, _) = extract_loads_from_expression(*address, 0); let (defs, cleaned_address, _) = extract_loads_from_expression(*address, 0);
let mut ir_defs: Vec<IrDef> = defs let mut ir_defs: Vec<IrDef> =
.into_iter() defs.into_iter().map(|def| def.into_ir_load()).collect();
.map(|def| def.into_ir_assignment())
.collect();
ir_defs.push(IrDef::Load { ir_defs.push(IrDef::Load {
address: cleaned_address.into(), address: cleaned_address.into(),
var: self.lhs.into(), var: self.lhs.into(),
...@@ -74,10 +72,8 @@ impl Def { ...@@ -74,10 +72,8 @@ impl Def {
let (mut more_defs, cleaned_value, _) = let (mut more_defs, cleaned_value, _) =
extract_loads_from_expression(*value, counter); extract_loads_from_expression(*value, counter);
defs.append(&mut more_defs); defs.append(&mut more_defs);
let mut ir_defs: Vec<IrDef> = defs let mut ir_defs: Vec<IrDef> =
.into_iter() defs.into_iter().map(|def| def.into_ir_load()).collect();
.map(|def| def.into_ir_assignment())
.collect();
ir_defs.push(IrDef::Store { ir_defs.push(IrDef::Store {
address: cleaned_address.into(), address: cleaned_address.into(),
value: cleaned_value.into(), value: cleaned_value.into(),
...@@ -89,46 +85,70 @@ impl Def { ...@@ -89,46 +85,70 @@ impl Def {
true_exp, true_exp,
false_exp, false_exp,
} => { } => {
// We only match for conditional stores. let (defs, cleaned_if_then_else, _) = extract_loads_from_expression(
// Other usages of the `IfThenElse`-expression will result in panics. Expression::IfThenElse {
let (address, value) = match (*true_exp, *false_exp) { condition,
(Expression::Store { address, value, .. }, Expression::Var(var)) true_exp,
| (Expression::Var(var), Expression::Store { address, value, .. }) false_exp,
if var == self.lhs =>
{
(address, value)
}
_ => panic!(),
};
let (mut defs, _cleaned_condition, counter) =
extract_loads_from_expression(*condition, 0);
let (mut more_defs, cleaned_adress, counter) =
extract_loads_from_expression(*address, counter);
let (mut even_more_defs, cleaned_value, _) =
extract_loads_from_expression(*value, counter);
defs.append(&mut more_defs);
defs.append(&mut even_more_defs);
let mut ir_defs: Vec<IrDef> = defs
.into_iter()
.map(|def| def.into_ir_assignment())
.collect();
ir_defs.push(IrDef::Store {
address: cleaned_adress.into(),
value: IrExpression::Unknown {
description: "BAP conditional store".into(),
size: cleaned_value.bitsize().into(),
}, },
0,
);
let mut ir_defs: Vec<IrDef> =
defs.into_iter().map(|def| def.into_ir_load()).collect();
if let Expression::IfThenElse {
condition: _,
true_exp,
false_exp,
} = cleaned_if_then_else
{
match (*true_exp, *false_exp) {
(Expression::Store { address, value, .. }, Expression::Var(var))
| (Expression::Var(var), Expression::Store { address, value, .. })
if var == self.lhs =>
{
// The IfThenElse-expression is a conditional store to memory
ir_defs.push(IrDef::Store {
address: IrExpression::from(*address),
value: IrExpression::Unknown {
description: "BAP conditional store".into(),
size: value.bitsize().into(),
},
});
}
_ => ir_defs.push(IrDef::Assign {
var: self.lhs.clone().into(),
value: IrExpression::Unknown {
description: "BAP IfThenElse expression".into(),
size: self.lhs.bitsize().unwrap().into(),
},
}),
}
ir_defs
} else {
panic!()
}
}
_ => {
let (defs, cleaned_rhs, _) = extract_loads_from_expression(self.rhs, 0);
let mut ir_defs: Vec<IrDef> =
defs.into_iter().map(|def| def.into_ir_load()).collect();
ir_defs.push(IrDef::Assign {
var: self.lhs.into(),
value: cleaned_rhs.into(),
}); });
ir_defs ir_defs
} }
_ => vec![self.into_ir_assignment()],
} }
} }
fn into_ir_assignment(self) -> IrDef { fn into_ir_load(self) -> IrDef {
IrDef::Assign { if let Expression::Load { address, .. } = self.rhs {
var: self.lhs.into(), IrDef::Load {
value: self.rhs.into(), address: IrExpression::from(*address),
var: self.lhs.into(),
}
} else {
panic!()
} }
} }
} }
...@@ -223,9 +243,25 @@ impl From<Blk> for IrBlk { ...@@ -223,9 +243,25 @@ impl From<Blk> for IrBlk {
let ir_jmp_terms = blk let ir_jmp_terms = blk
.jmps .jmps
.into_iter() .into_iter()
.map(|jmp_term| Term { .map(|jmp_term| {
tid: jmp_term.tid, let (jmp, defs) = extract_loads_from_jump(jmp_term.term);
term: jmp_term.term.into(), let mut ir_defs = Vec::new();
for def in defs.into_iter() {
ir_defs.append(&mut def.into_ir_defs());
}
for (counter, ir_def) in ir_defs.into_iter().enumerate() {
ir_def_terms.push(Term {
tid: Tid {
id: format!("{}_{}", jmp_term.tid.id, counter),
address: jmp_term.tid.address.clone(),
},
term: ir_def,
});
}
Term {
tid: jmp_term.tid,
term: jmp.into(),
}
}) })
.collect(); .collect();
IrBlk { IrBlk {
...@@ -450,7 +486,30 @@ fn extract_loads_from_expression(expr: Expression, counter: u64) -> (Vec<Def>, E ...@@ -450,7 +486,30 @@ fn extract_loads_from_expression(expr: Expression, counter: u64) -> (Vec<Def>, E
(defs, Var(temp_var), counter) (defs, Var(temp_var), counter)
} }
Var(_) | Const(_) | Unknown { .. } => (Vec::new(), expr, counter), Var(_) | Const(_) | Unknown { .. } => (Vec::new(), expr, counter),
Store { .. } | Let { .. } | IfThenElse { .. } => panic!(), Store { .. } | Let { .. } => panic!(),
IfThenElse {
condition,
true_exp,
false_exp,
} => {
let (mut defs, cleaned_cond, counter) =
extract_loads_from_expression(*condition, counter);
let (mut defs_true, cleaned_true, counter) =
extract_loads_from_expression(*true_exp, counter);
let (mut defs_false, cleaned_false, counter) =
extract_loads_from_expression(*false_exp, counter);
defs.append(&mut defs_true);
defs.append(&mut defs_false);
(
defs,
IfThenElse {
condition: Box::new(cleaned_cond),
true_exp: Box::new(cleaned_true),
false_exp: Box::new(cleaned_false),
},
counter,
)
}
BinOp { op, lhs, rhs } => { BinOp { op, lhs, rhs } => {
let (mut defs, cleaned_lhs, counter) = extract_loads_from_expression(*lhs, counter); let (mut defs, cleaned_lhs, counter) = extract_loads_from_expression(*lhs, counter);
let (mut defs_rhs, cleaned_rhs, counter) = extract_loads_from_expression(*rhs, counter); let (mut defs_rhs, cleaned_rhs, counter) = extract_loads_from_expression(*rhs, counter);
...@@ -521,6 +580,36 @@ fn extract_loads_from_expression(expr: Expression, counter: u64) -> (Vec<Def>, E ...@@ -521,6 +580,36 @@ fn extract_loads_from_expression(expr: Expression, counter: u64) -> (Vec<Def>, E
} }
} }
fn extract_loads_from_jump(mut jmp: Jmp) -> (Jmp, Vec<Def>) {
let mut counter = 0;
let mut defs = Vec::new();
if let Some(condition) = jmp.condition {
let (mut new_defs, cleaned_condition, new_counter) =
extract_loads_from_expression(condition, counter);
counter = new_counter;
defs.append(&mut new_defs);
jmp.condition = Some(cleaned_condition);
}
match jmp.kind {
JmpKind::Goto(Label::Indirect(ref mut target)) => {
let (mut new_defs, cleaned_target, _) =
extract_loads_from_expression(target.clone(), counter);
defs.append(&mut new_defs);
*target = cleaned_target;
}
JmpKind::Call(ref mut call) => {
if let Label::Indirect(ref mut target) = call.target {
let (mut new_defs, cleaned_target, _) =
extract_loads_from_expression(target.clone(), counter);
defs.append(&mut new_defs);
*target = cleaned_target;
}
}
_ => (),
}
(jmp, defs)
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment