mirror of
				https://github.com/yuzu-emu/unicorn.git
				synced 2025-10-30 04:20:35 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			86 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Haskell
		
	
	
	
	
	
			
		
		
	
	
			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
 |