pub fn backward_analysis(ssa: &SSAStorage, sp_name: String) -> HashMap<LValueRef, i64> {
    let mut stack_offset: HashMap<LValueRef, i64> = HashMap::new();
    let mut worklist: VecDeque<LValueRef> = VecDeque::new();
    let mut visited: HashSet<LValueRef> = HashSet::new();

    // Initial the last SP register offset to ZERO.
    let reg_state = registers_in_err!(ssa, exit_node_err!(ssa));
    let nodes = ssa.operands_of(reg_state);
    for node in &nodes {
        if ssa.registers(*node).contains(&sp_name) {
            stack_offset.insert(*node, 0);
            worklist.push_back(*node);
        }
    }

    while let Some(node) = worklist.pop_front() {
        if !visited.contains(&node) {
            visited.insert(node);
        } else {
            continue;
        }

        let base = stack_offset
            .get(&node)
            .map(|x| x.clone())
            .unwrap_or_else(|| {
                radeco_err!("node not found from stack_offset");
                0
            });
        let args = ssa.operands_of(node);

        let users = ssa.uses_of(node);
        for user in users {
            match ssa.opcode(user) {
                Some(MOpcode::OpZeroExt(_)) | Some(MOpcode::OpNarrow(_)) => {
                    stack_offset.insert(user, base);
                    worklist.push_back(user);
                }
                _ => {}
            }
        }

        // The node maybe a comment, for call statements made it
        if ssa.comment(node).is_some() {
            continue;
        }

        // Every SP met at one phi node will have the same value.
        if ssa.is_phi(node) {
            for arg in args {
                stack_offset.insert(arg, base);
                worklist.push_back(arg);
            }
            continue;
        }

        // Consider exprission.
        if ssa.opcode(node).is_none() {
            continue;
        }

        let opc = ssa.opcode(node).unwrap();
        match opc {
            MOpcode::OpZeroExt(_) | MOpcode::OpNarrow(_) => {
                stack_offset.insert(args[0], base);
                worklist.push_back(args[0]);
            }
            MOpcode::OpSub => {
                if let Some(MOpcode::OpConst(num)) = ssa.opcode(args[1]) {
                    stack_offset.insert(args[0], base + (num as i64));
                    worklist.push_back(args[0]);
                }
            }
            MOpcode::OpAdd => {
                if let Some(MOpcode::OpConst(num)) = ssa.opcode(args[0]) {
                    stack_offset.insert(args[1], base - (num as i64));
                    worklist.push_back(args[1]);
                }
            }
            _ => {}
        }
    }

    radeco_trace!("CallFixer|Stack_offset: {:?}", stack_offset);
    stack_offset
}
/// Analyze stack offset backward, by assuming the stack of last
/// SP register is ZERO.
/// You have to offer RadecoIL SSA and SP register name into analyzer.
Analyze stack offset backward, by assuming the stack of last
SP register is ZERO.
You have to offer RadecoIL SSA and SP register name into analyzer.
Analyze stack offset backward by assuming the stack of last SP register is ZERO . You have to offer RadecoIL SSA and SP register name into analyzer .
pub fn backward_analysis(ssa: &SSAStorage, sp_name: String) -> HashMap<LValueRef, i64> {
    let mut stack_offset: HashMap<LValueRef, i64> = HashMap::new();
    let mut worklist: VecDeque<LValueRef> = VecDeque::new();
    let mut visited: HashSet<LValueRef> = HashSet::new();
    // Initial the last SP register offset to ZERO.
    let reg_state = registers_in_err!(ssa, exit_node_err!(ssa));
    let nodes = ssa.operands_of(reg_state);
    for node in &nodes {
        if ssa.registers(*node).contains(&sp_name) {
            stack_offset.insert(*node, 0);
            worklist.push_back(*node);
        }
    }
    while let Some(node) = worklist.pop_front() {
        if !visited.contains(&node) {
            visited.insert(node);
        } else {
            continue;
        }
        let base = stack_offset
            .get(&node)
            .map(|x| x.clone())
            .unwrap_or_else(|| {
                radeco_err!("node not found from stack_offset");
                0
            });
        let args = ssa.operands_of(node);
        let users = ssa.uses_of(node);
        for user in users {
            match ssa.opcode(user) {
                Some(MOpcode::OpZeroExt(_)) | Some(MOpcode::OpNarrow(_)) => {
                    stack_offset.insert(user, base);
                    worklist.push_back(user);
                }
                _ => {}
            }
        }
        // The node maybe a comment, for call statements made it
        if ssa.comment(node).is_some() {
            continue;
        }
        // Every SP met at one phi node will have the same value.
        if ssa.is_phi(node) {
            for arg in args {
                stack_offset.insert(arg, base);
                worklist.push_back(arg);
            }
            continue;
        }
        // Consider exprission.
        if ssa.opcode(node).is_none() {
            continue;
        }
        let opc = ssa.opcode(node).unwrap();
        match opc {
            MOpcode::OpZeroExt(_) | MOpcode::OpNarrow(_) => {
                stack_offset.insert(args[0], base);
                worklist.push_back(args[0]);
            }
            MOpcode::OpSub => {
                if let Some(MOpcode::OpConst(num)) = ssa.opcode(args[1]) {
                    stack_offset.insert(args[0], base + (num as i64));
                    worklist.push_back(args[0]);
                }
            }
            MOpcode::OpAdd => {
                if let Some(MOpcode::OpConst(num)) = ssa.opcode(args[0]) {
                    stack_offset.insert(args[1], base - (num as i64));
                    worklist.push_back(args[1]);
                }
            }
            _ => {}
        }
    }
    radeco_trace!("CallFixer|Stack_offset: {:?}", stack_offset);
    stack_offset
}
pub fn backward_analysis ( ssa : & SSAStorage , sp_name : String ) -> HashMap < LValueRef , i64 > { let mut stack_offset : HashMap < LValueRef , i64 > = HashMap :: new ( ) ; let mut worklist : VecDeque < LValueRef > = VecDeque :: new ( ) ; let mut visited : HashSet < LValueRef > = HashSet :: new ( ) ; // Initial the last SP register offset to ZERO. let reg_state = registers_in_err ! ( ssa exit_node_err ( ssa ) ) ; let nodes = ssa . operands_of ( reg_state ) ; for node in & nodes { if ssa . registers ( * node ) . contains ( & sp_name ) { stack_offset . insert ( * node , 0 ) ; worklist . push_back ( * node ) ; } } while let Some ( node ) = worklist . pop_front ( ) { if ! visited . contains ( & node ) { visited . insert ( node ) ; } else { continue ; } let base = stack_offset . get ( & node ) . map ( | x | x . clone ( ) ) . unwrap_or_else ( | | { radeco_err ! ( " " ) ; 0 } ) ; let args = ssa . operands_of ( node ) ; let users = ssa . uses_of ( node ) ; for user in users { match ssa . opcode ( user ) { Some ( MOpcode :: OpZeroExt ( _ ) ) | Some ( MOpcode :: OpNarrow ( _ ) ) => { stack_offset . insert ( user , base ) ; worklist . push_back ( user ) ; } _ => { } } } // The node maybe a comment, for call statements made it if ssa . comment ( node ) . is_some ( ) { continue ; } // Every SP met at one phi node will have the same value. if ssa . is_phi ( node ) { for arg in args { stack_offset . insert ( arg , base ) ; worklist . push_back ( arg ) ; } continue ; } // Consider exprission. if ssa . opcode ( node ) . is_none ( ) { continue ; } let opc = ssa . opcode ( node ) . unwrap ( ) ; match opc { MOpcode :: OpZeroExt ( _ ) | MOpcode :: OpNarrow ( _ ) => { stack_offset . insert ( args [ 0 ] , base ) ; worklist . push_back ( args [ 0 ] ) ; } MOpcode :: OpSub => { if let Some ( MOpcode :: OpConst ( num ) ) = ssa . opcode ( args [ 1 ] ) { stack_offset . insert ( args [ 0 ] , base + ( num as i64 ) ) ; worklist . push_back ( args [ 0 ] ) ; } } MOpcode :: OpAdd => { if let Some ( MOpcode :: OpConst ( num ) ) = ssa . opcode ( args [ 0 ] ) { stack_offset . insert ( args [ 1 ] , base - ( num as i64 ) ) ; worklist . push_back ( args [ 1 ] ) ; } } _ => { } } } radeco_trace ! ( " " stack_offset ) ; stack_offset }
Analyze stack offset backward, by assuming the stack of last
SP register is ZERO.
Analyze stack offset backward by assuming the stack of last SP register is ZERO .
ssa
&SSAStorage
sp_name
String
ssa
&SSAStorage
sp_name
String