[macaw-arm] initial (incomplete) implementation of checkForReturnAddr.

The ArchitectureInfo checkForReturnAddr is used to check if a specific
value corresponds to the symbolic "ReturnAddr", indicating that the
target is the original call location (this is used to identify
tail-call recursion or identify that a return has been performed from
the primary function via identifyReturn).

The current implementation simply checks for ReturnAddr in the Link
Register (LR), but it needs to be enhanced to detect ARM semantic
manipulation of ReturnAddr (clearing the low bit(s), etc.).
This commit is contained in:
Kevin Quick 2018-12-14 15:06:37 -08:00
parent 294299a8eb
commit d4c7f1f457
No known key found for this signature in database
GPG Key ID: E6D7733599CC0A21
2 changed files with 39 additions and 5 deletions

View File

@ -17,9 +17,12 @@ module Data.Macaw.ARM
import Data.Macaw.ARM.Arch
import Data.Macaw.ARM.Disassemble ( disassembleFn, initialBlockRegs )
import Data.Macaw.ARM.Eval
import Data.Macaw.ARM.Identify ( identifyCall, identifyReturn )
import Data.Macaw.ARM.Identify ( identifyCall, identifyReturn, isReturnValue )
import qualified Data.Macaw.ARM.ARMReg as ARMReg
import qualified Data.Macaw.ARM.Semantics.ARMSemantics as ARMSem
import qualified Data.Macaw.ARM.Semantics.ThumbSemantics as ThumbSem
import qualified Data.Macaw.CFG as MC
import Control.Lens ( (^.) )
import qualified Data.Macaw.Architecture.Info as MI
import qualified Data.Macaw.CFG.DemandSet as MDS
import qualified Data.Macaw.Memory as MM
@ -43,6 +46,7 @@ arm_linux_info =
, MI.absEvalArchStmt = absEvalArchStmt proxy
, MI.postCallAbsState = error "TBD: postCallAbsState proxy"
, MI.identifyCall = identifyCall proxy
, MI.checkForReturnAddr = \r s -> isReturnValue proxy s (r ^. MC.boundValue ARMReg.arm_LR)
, MI.identifyReturn = identifyReturn proxy
, MI.rewriteArchFn = rewritePrimFn
, MI.rewriteArchStmt = rewriteStmt

View File

@ -6,6 +6,7 @@
module Data.Macaw.ARM.Identify
( identifyCall
, identifyReturn
, isReturnValue
) where
import Control.Lens ( (^.) )
@ -13,11 +14,18 @@ import Data.Macaw.ARM.Arch
import Data.Macaw.AbsDomain.AbsState ( AbsProcessorState
, AbsValue(..)
, transferValue
, ppAbsValue
)
import qualified Data.Macaw.CFG as MC
import qualified Data.Macaw.Memory as MM
import qualified Data.Macaw.Types as MT
import qualified Data.Sequence as Seq
-- import Debug.Trace
debug :: Show a => a -> b -> b
-- debug = trace
debug = flip const
-- | Identifies a call statement, *after* the corresponding statement
-- has been performed. This can be tricky with ARM because there are
@ -49,7 +57,29 @@ identifyReturn :: ARMArchConstraints arm =>
-> MC.RegState (MC.ArchReg arm) (MC.Value arm ids)
-> AbsProcessorState (MC.ArchReg arm) ids
-> Maybe (Seq.Seq (MC.Stmt arm ids))
identifyReturn _ stmts s finalRegSt8 =
case transferValue finalRegSt8 (s^.MC.boundValue MC.ip_reg) of
ReturnAddr -> Just stmts
_ -> Nothing
identifyReturn arm stmts s finalRegSt8 =
if isReturnValue arm finalRegSt8 (s^.MC.boundValue MC.ip_reg)
then Just stmts
else Nothing
-- | Determines if the supplied value is the symbolic return address
-- from Macaw, modulo any ARM semantics operations (lots of ite caused
-- by the conditional execution bits for most instructions, clearing
-- of the low bits (1 in T32 mode, 2 in A32 mode).
isReturnValue :: ARMArchConstraints arm =>
proxy arm
-> AbsProcessorState (MC.ArchReg arm) ids
-> MC.Value arm ids (MT.BVType (MC.RegAddrWidth (MC.ArchReg arm)))
-> Bool
isReturnValue _ absProcState val =
case transferValue absProcState val of
ReturnAddr -> True
-- TBD: fill in the code here to recognize the expression that
-- clears the lower bit(s), along the lines of what is done by PPC
-- Identify.hs for the shifting operations.
o -> debug ("######################## Unrecognized return value: " <>
show (MC.ppValue 0 val) <>
" or " <>
show (ppAbsValue o)
) False