fn mark_preserved(
        &mut self,
        rfn_addr: &u64,
        entry_store: HashMap<String, i64>,
        exit_load: HashMap<String, i64>,
    ) -> Option<i64> {
        if self.rmod.functions.get_mut(rfn_addr).is_none() {
            radeco_err!("RadecoFunction Not Found!");
            return None;
        }
        let (preserves, sp_offset) = {
            let mut sp_offset: Option<i64> = None;
            let mut preserves: HashSet<String> = HashSet::new();
            for (name, en_offset) in entry_store {
                if let Some(ex_offset) = exit_load.get(&name).cloned() {
                    // Same reg name have appeared in entry and exit;
                    match sp_offset {
                        None => {
                            sp_offset = Some(en_offset - ex_offset);
                            preserves.insert(name);
                        }
                        Some(off) if en_offset - ex_offset == off => {
                            preserves.insert(name);
                        }
                        Some(_) => {
                            preserves.clear();
                            sp_offset = None;
                            break;
                        }
                    }
                }
            }
            (preserves, sp_offset)
        };

        radeco_trace!("CallFixer|{:?} with {:?}", preserves, sp_offset);

        // Store data into RadecoFunction
        {
            let rfn = self.rmod.functions.get_mut(rfn_addr).unwrap();
            for mut bind in rfn.bindings_mut().into_iter() {
                if preserves.contains(bind.name()) {
                    bind.mark_preserved();
                }
                radeco_trace!("CallFixer|Bind: {:?}", bind);
            }
        }

        sp_offset
    }
// Before we calcluate, we have to finger out the SP offset between entry node
// and exit bode. The reason cause this difference is that in SSA form, we didn't
// split OpCall into STORE PC stage and JMP stage, but we split RET statements
// into LOAD PC stage and JMP stage. That means, SP at exit point will be higher
// than SP at entry point.
// TODO: We could not finger whether the STORE PC stage in Call use a PUSH stack or
// MOV register. Thus, we will do a probable estimation in analysis function and
// check it in the reanalysis stage.
Before we calcluate, we have to finger out the SP offset between entry node
and exit bode. The reason cause this difference is that in SSA form, we didn't
split OpCall into STORE PC stage and JMP stage, but we split RET statements
into LOAD PC stage and JMP stage. That means, SP at exit point will be higher
than SP at entry point.
TODO: We could not finger whether the STORE PC stage in Call use a PUSH stack or
MOV register. Thus, we will do a probable estimation in analysis function and
check it in the reanalysis stage.
Before we calcluate we have to finger out the SP offset between entry node and exit bode . The reason cause this difference is that in SSA form we didn ' t split OpCall into STORE PC stage and JMP stage but we split RET statements into LOAD PC stage and JMP stage . That means SP at exit point will be higher than SP at entry point . TODO : We could not finger whether the STORE PC stage in Call use a PUSH stack or MOV register . Thus we will do a probable estimation in analysis function and check it in the reanalysis stage .
fn mark_preserved(
        &mut self,
        rfn_addr: &u64,
        entry_store: HashMap<String, i64>,
        exit_load: HashMap<String, i64>,
    ) -> Option<i64> {
        if self.rmod.functions.get_mut(rfn_addr).is_none() {
            radeco_err!("RadecoFunction Not Found!");
            return None;
        }
        let (preserves, sp_offset) = {
            let mut sp_offset: Option<i64> = None;
            let mut preserves: HashSet<String> = HashSet::new();
            for (name, en_offset) in entry_store {
                if let Some(ex_offset) = exit_load.get(&name).cloned() {
                    // Same reg name have appeared in entry and exit;
                    match sp_offset {
                        None => {
                            sp_offset = Some(en_offset - ex_offset);
                            preserves.insert(name);
                        }
                        Some(off) if en_offset - ex_offset == off => {
                            preserves.insert(name);
                        }
                        Some(_) => {
                            preserves.clear();
                            sp_offset = None;
                            break;
                        }
                    }
                }
            }
            (preserves, sp_offset)
        };
        radeco_trace!("CallFixer|{:?} with {:?}", preserves, sp_offset);
        // Store data into RadecoFunction
        {
            let rfn = self.rmod.functions.get_mut(rfn_addr).unwrap();
            for mut bind in rfn.bindings_mut().into_iter() {
                if preserves.contains(bind.name()) {
                    bind.mark_preserved();
                }
                radeco_trace!("CallFixer|Bind: {:?}", bind);
            }
        }
        sp_offset
    }
fn mark_preserved ( & mut self , rfn_addr : & u64 , entry_store : HashMap < String , i64 > , exit_load : HashMap < String , i64 > , ) -> Option < i64 > { if self . rmod . functions . get_mut ( rfn_addr ) . is_none ( ) { radeco_err ! ( " " ) ; return None ; } let ( preserves , sp_offset ) = { let mut sp_offset : Option < i64 > = None ; let mut preserves : HashSet < String > = HashSet :: new ( ) ; for ( name , en_offset ) in entry_store { if let Some ( ex_offset ) = exit_load . get ( & name ) . cloned ( ) { // Same reg name have appeared in entry and exit; match sp_offset { None => { sp_offset = Some ( en_offset - ex_offset ) ; preserves . insert ( name ) ; } Some ( off ) if en_offset - ex_offset == off => { preserves . insert ( name ) ; } Some ( _ ) => { preserves . clear ( ) ; sp_offset = None ; break ; } } } } ( preserves , sp_offset ) } ; radeco_trace ! ( " " preserves sp_offset ) ; // Store data into RadecoFunction { let rfn = self . rmod . functions . get_mut ( rfn_addr ) . unwrap ( ) ; for mut bind in rfn . bindings_mut ( ) . into_iter ( ) { if preserves . contains ( bind . name ( ) ) { bind . mark_preserved ( ) ; } radeco_trace ! ( " " bind ) ; } } sp_offset }
Before we calcluate, we have to finger out the SP offset between entry node
and exit bode.
Before we calcluate we have to finger out the SP offset between entry node and exit bode .
&mut self
rfn_addr
&u64
entry_store
HashMap<String, i64>
exit_load
HashMap<String, i64>
&mut self
rfn_addr
&u64
entry_store
HashMap<String, i64>
exit_load
HashMap<String, i64>