unicorn/bindings/haskell/samples/SampleArm64.hs
2016-04-08 23:31:13 +10:00

86 lines
2.4 KiB
Haskell

-- Sample code to demonstrate how to emulate ARM64 code
import Unicorn
import Unicorn.Hook
import qualified Unicorn.CPU.Arm64 as Arm64
import qualified Data.ByteString as BS
import Data.Word
import qualified Numeric as N (showHex)
-- Code to be emulated
--
-- add x11, x13, x15
armCode :: BS.ByteString
armCode = BS.pack [0xab, 0x01, 0x0f, 0x8b]
-- Memory address where emulation starts
address :: Word64
address = 0x10000
-- Pretty-print integral as hex
showHex :: (Integral a, Show a) => a -> String
showHex =
flip N.showHex ""
-- Calculate code length
codeLength :: Num a => BS.ByteString -> a
codeLength =
fromIntegral . BS.length
hookBlock :: BlockHook ()
hookBlock _ addr size _ =
putStrLn $ ">>> Tracing basic block at 0x" ++ showHex addr ++
", block size = 0x" ++ (maybe "0" showHex size)
hookCode :: CodeHook ()
hookCode _ addr size _ =
putStrLn $ ">>> Tracing instruction at 0x" ++ showHex addr ++
", instruction size = 0x" ++ (maybe "0" showHex size)
testArm64 :: IO ()
testArm64 = do
putStrLn "Emulate ARM64 code"
result <- runEmulator $ do
-- Initialize emulator in ARM mode
uc <- open ArchArm64 [ModeArm]
-- Map 2MB memory for this emulation
memMap uc address (2 * 1024 * 1024) [ProtAll]
-- Write machine code to be emulated to memory
memWrite uc address armCode
-- Initialize machine registers
regWrite uc Arm64.X11 0x1234
regWrite uc Arm64.X13 0x6789
regWrite uc Arm64.X15 0x3333
-- Tracing all basic blocks with customized callback
blockHookAdd uc hookBlock () 1 0
-- Tracing one instruction at address with customized callback
codeHookAdd uc hookCode () address address
-- Emulate machine code in infinite time (last param = Nothing), or
-- when finishing all the code
let codeLen = codeLength armCode
start uc address (address + codeLen) Nothing Nothing
-- Return the results
x11 <- regRead uc Arm64.X11
return x11
case result of
Right x11 -> do
-- Now print out some registers
putStrLn $ ">>> Emulation done. Below is the CPU context"
putStrLn $ ">>> X11 = 0x" ++ showHex x11
Left err -> putStrLn $ "Failed with error: " ++ show err ++ " (" ++
strerror err ++ ")"
main :: IO ()
main =
testArm64