Enum evmil::dfa::AbstractValue
source · pub enum AbstractValue {
Known(usize),
Unknown,
}
Expand description
An abstract value is either a known constant, or an unknown (i.e. arbitrary value).
Variants§
Implementations§
source§impl AbstractValue
impl AbstractValue
sourcepub fn merge(self, other: AbstractValue) -> AbstractValue
pub fn merge(self, other: AbstractValue) -> AbstractValue
Examples found in repository?
src/dfa/stack.rs (line 184)
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
pub fn merge(self, other: &AbstractStack) -> Self {
let slen = self.upper.len();
let olen = other.upper.len();
// Determine common upper length
let n = cmp::min(slen,olen);
// Normalise lower segments
let lself = self.lower.add(slen - n);
let lother = other.lower.add(olen - n);
let mut merger = AbstractStack::new(lself.union(&lother),Vec::new());
// Push merged items from upper segment
for i in (0..n).rev() {
let ithself = self.peek(i);
let ithother = other.peek(i);
merger = merger.push(ithself.merge(ithother));
}
// Done
merger
}
sourcepub fn is_known(&self) -> bool
pub fn is_known(&self) -> bool
Examples found in repository?
src/disassembler.rs (line 315)
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
pub fn build(mut self) -> Self {
let mut changed = true;
//
while changed {
// Reset indicator
changed = false;
// Iterate blocks in order
for i in 0..self.blocks.len() {
// Sanity check whether block unreachable.
if !self.is_block_reachable(i) { continue; }
// Yes, is reachable so continue.
let blk = &self.blocks[i];
let mut ctx = self.contexts[i].clone();
let mut pc = blk.start;
// println!("BLOCK (start={}, end={}): {:?}", pc, blk.end, i);
// println!("CONTEXT (pc={}): {}", pc, ctx);
// Parse the block
while pc < blk.end {
// Decode instruction at the current position
let insn = Instruction::decode(pc,&self.bytes);
// Check whether a branch is possible
if insn.can_branch() && ctx.peek(0).is_known() {
// Determine branch target
let target = ctx.peek(0).unwrap();
// Determine branch context
let branch_ctx = ctx.branch(target,&insn);
// Convert target into block ID.
let block_id = self.get_enclosing_block_id(target);
// println!("Branch: target={} (block {})",target,block_id);
// println!("Before merge (pc={}): {}", pc, self.contexts[block_id]);
// Merge in updated state
changed |= self.contexts[block_id].merge(branch_ctx);
// println!("After merge (pc={}): {}", pc, self.contexts[block_id]);
}
// Apply the transfer function!
// print!("{:#08x}: {}",pc,ctx);
ctx = ctx.transfer(&insn);
// println!(" ==>\t{:?}\t==> {}",insn,ctx);
// Next instruction
pc = pc + insn.length(&[]);
}
// Merge state into following block.
if (i+1) < self.blocks.len() {
changed |= self.contexts[i+1].merge(ctx);
}
}
}
self
}
sourcepub fn unwrap(&self) -> usize
pub fn unwrap(&self) -> usize
Examples found in repository?
src/disassembler.rs (line 317)
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
pub fn build(mut self) -> Self {
let mut changed = true;
//
while changed {
// Reset indicator
changed = false;
// Iterate blocks in order
for i in 0..self.blocks.len() {
// Sanity check whether block unreachable.
if !self.is_block_reachable(i) { continue; }
// Yes, is reachable so continue.
let blk = &self.blocks[i];
let mut ctx = self.contexts[i].clone();
let mut pc = blk.start;
// println!("BLOCK (start={}, end={}): {:?}", pc, blk.end, i);
// println!("CONTEXT (pc={}): {}", pc, ctx);
// Parse the block
while pc < blk.end {
// Decode instruction at the current position
let insn = Instruction::decode(pc,&self.bytes);
// Check whether a branch is possible
if insn.can_branch() && ctx.peek(0).is_known() {
// Determine branch target
let target = ctx.peek(0).unwrap();
// Determine branch context
let branch_ctx = ctx.branch(target,&insn);
// Convert target into block ID.
let block_id = self.get_enclosing_block_id(target);
// println!("Branch: target={} (block {})",target,block_id);
// println!("Before merge (pc={}): {}", pc, self.contexts[block_id]);
// Merge in updated state
changed |= self.contexts[block_id].merge(branch_ctx);
// println!("After merge (pc={}): {}", pc, self.contexts[block_id]);
}
// Apply the transfer function!
// print!("{:#08x}: {}",pc,ctx);
ctx = ctx.transfer(&insn);
// println!(" ==>\t{:?}\t==> {}",insn,ctx);
// Next instruction
pc = pc + insn.length(&[]);
}
// Merge state into following block.
if (i+1) < self.blocks.len() {
changed |= self.contexts[i+1].merge(ctx);
}
}
}
self
}
Trait Implementations§
source§impl Clone for AbstractValue
impl Clone for AbstractValue
source§fn clone(&self) -> AbstractValue
fn clone(&self) -> AbstractValue
Returns a copy of the value. Read more
1.0.0 · source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source
. Read moresource§impl Debug for AbstractValue
impl Debug for AbstractValue
source§impl Display for AbstractValue
impl Display for AbstractValue
source§impl PartialEq<AbstractValue> for AbstractValue
impl PartialEq<AbstractValue> for AbstractValue
source§fn eq(&self, other: &AbstractValue) -> bool
fn eq(&self, other: &AbstractValue) -> bool
This method tests for
self
and other
values to be equal, and is used
by ==
.