mirror of
https://github.com/yuzu-emu/unicorn
synced 2024-11-25 15:19:00 +00:00
85 lines
2.4 KiB
Haskell
85 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
|