X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=Mate%2FX86TrapHandling.hs;h=325f7928c44eb82401d32a44b957ad9a416336ea;hb=8981d77c48cc12673620159b4f6b8274b07abddf;hp=0e07cd5e29351e38c669e50530c0c241a6f66358;hpb=e77e74e6bbc04c523f1468d21b14167b7eb910f7;p=mate.git diff --git a/Mate/X86TrapHandling.hs b/Mate/X86TrapHandling.hs index 0e07cd5..325f792 100644 --- a/Mate/X86TrapHandling.hs +++ b/Mate/X86TrapHandling.hs @@ -8,6 +8,7 @@ module Mate.X86TrapHandling ( ) where import qualified Data.Map as M +import qualified Data.ByteString.Lazy as B import Foreign import Foreign.C.Types @@ -24,57 +25,64 @@ data TrapType = | StaticFieldAccess | VirtualMethodCall Bool | InterfaceMethodCall Bool + | InstanceOfMiss B.ByteString + | NoKnownTrap String -getTrapType :: TrapMap -> CUInt -> CUInt -> TrapType +getTrapType :: TrapMap -> CPtrdiff -> CPtrdiff -> TrapType getTrapType tmap signal_from from2 = case M.lookup (fromIntegral signal_from) tmap of (Just (StaticMethod _)) -> StaticMethodCall (Just (StaticField _)) -> StaticFieldAccess - (Just _) -> error "getTrapMap: doesn't happen" + (Just (InstanceOf cn)) -> InstanceOfMiss cn + (Just _) -> NoKnownTrap "getTrapMap: doesn't happen" -- maybe we've a hit on the second `from' value Nothing -> case M.lookup (fromIntegral from2) tmap of (Just (VirtualMethod imm8 _)) -> VirtualMethodCall imm8 (Just (InterfaceMethod imm8 _)) -> InterfaceMethodCall imm8 - (Just _) -> error "getTrapType: abort #1 :-(" - Nothing -> error $ "getTrapType: abort #2 :-(" ++ show signal_from ++ ", " ++ show from2 ++ ", " ++ show tmap + (Just _) -> NoKnownTrap "getTrapType: abort #1 :-(" + Nothing -> NoKnownTrap $ "getTrapType: abort #2 :-(" ++ show signal_from ++ ", " ++ show from2 ++ ", " ++ show tmap -foreign export ccall mateHandler :: CUInt -> CUInt -> CUInt -> CUInt -> IO CUInt -mateHandler :: CUInt -> CUInt -> CUInt -> CUInt -> IO CUInt -mateHandler eip eax ebx esp = do +foreign export ccall mateHandler :: CPtrdiff -> CPtrdiff -> CPtrdiff -> CPtrdiff -> CPtrdiff -> IO CPtrdiff +mateHandler :: CPtrdiff -> CPtrdiff -> CPtrdiff -> CPtrdiff -> CPtrdiff -> IO CPtrdiff +mateHandler eip eax ebx esp esi = do callerAddr <- callerAddrFromStack esp tmap <- getTrapMap case getTrapType tmap eip callerAddr of StaticMethodCall -> staticCallHandler eip StaticFieldAccess -> staticFieldHandler eip + (InstanceOfMiss cn) -> instanceOfMissHandler eip cn VirtualMethodCall imm8 -> invokeHandler eax eax esp imm8 InterfaceMethodCall imm8 -> invokeHandler eax ebx esp imm8 + NoKnownTrap err -> + case esi of + 0x13371234 -> return (-1) + _ -> error err -staticCallHandler :: CUInt -> IO CUInt +staticCallHandler :: CPtrdiff -> IO CPtrdiff staticCallHandler eip = do - -- the actual insn to patch is displaced by two bytes - let insn_ptr = intPtrToPtr (fromIntegral (eip - 2)) :: Ptr CUChar - -- call offset is displaced by one byte - let imm_ptr = intPtrToPtr (fromIntegral (eip - 1)) :: Ptr CUInt + -- the actual insn to patch as pointer + let insn_ptr = intPtrToPtr (fromIntegral eip) :: Ptr CUChar + -- call offset is displaced by one byte (as the first byte is the opcode) + let imm_ptr = intPtrToPtr (fromIntegral (eip + 1)) :: Ptr CPtrdiff -- in codegen we set the immediate to some magic value -- in order to produce a SIGILL signal. we also do a safety -- check here, if we're really the "owner" of this signal. checkMe <- peek imm_ptr - if checkMe == 0x90ffff90 then + if checkMe == 0x909090ff then do entryAddr <- getMethodEntry eip 0 - poke insn_ptr 0xe8 -- call opcode - -- it's a relative call, so we have to calculate the offset. why "+ 3"? + poke insn_ptr 0xe8 -- `call' opcode + -- it's a relative call, so we have to calculate the offset. why "+ 5"? -- (1) the whole insn is 5 bytes long - -- (2) begin of insn is displaced by 2 bytes - -- (3) offset is calculated wrt to the beginning of the next insn - poke imm_ptr (entryAddr - (eip + 3)) - return (eip - 2) + -- (2) offset is calculated wrt to the beginning of the next insn + poke imm_ptr (entryAddr - (eip + 5)) + return eip else error "staticCallHandler: something is wrong here. abort\n" -staticFieldHandler :: CUInt -> IO CUInt +staticFieldHandler :: CPtrdiff -> IO CPtrdiff staticFieldHandler eip = do -- patch the offset here, first two bytes are part of the insn (opcode + reg) - let imm_ptr = intPtrToPtr (fromIntegral (eip + 2)) :: Ptr CUInt + let imm_ptr = intPtrToPtr (fromIntegral (eip + 2)) :: Ptr CPtrdiff checkMe <- peek imm_ptr if checkMe == 0x00000000 then do @@ -82,7 +90,22 @@ staticFieldHandler eip = do return eip else error "staticFieldHandler: something is wrong here. abort.\n" -invokeHandler :: CUInt -> CUInt -> CUInt -> Bool -> IO CUInt +instanceOfMissHandler :: CPtrdiff -> B.ByteString -> IO CPtrdiff +instanceOfMissHandler eip classname = do + -- first byte is going to be the opcode + let insn_ptr = intPtrToPtr (fromIntegral eip) :: Ptr CUChar + -- the next four bytes are the immediate + let imm_ptr = intPtrToPtr (fromIntegral (eip + 1)) :: Ptr CPtrdiff + checkMe <- peek imm_ptr + if checkMe == 0x909090ff then -- safety check... + do + mtable <- getMethodTable classname + poke imm_ptr (fromIntegral mtable) + poke insn_ptr 0xba -- `mov edx' opcode + return eip + else error "instanceOfMissHandler: something is wrong here. abort.\n" + +invokeHandler :: CPtrdiff -> CPtrdiff -> CPtrdiff -> Bool -> IO CPtrdiff invokeHandler method_table table2patch esp imm8 = do -- table2patch: note, that can be a method-table or a interface-table callerAddr <- callerAddrFromStack esp @@ -93,18 +116,18 @@ invokeHandler method_table table2patch esp imm8 = do return entryAddr -callerAddrFromStack :: CUInt -> IO CUInt +callerAddrFromStack :: CPtrdiff -> IO CPtrdiff callerAddrFromStack = peek . intPtrToPtr . fromIntegral -offsetOfCallInsn8 :: CUInt -> IO CUInt +offsetOfCallInsn8 :: CPtrdiff -> IO CPtrdiff offsetOfCallInsn8 esp = do - let ret_ptr = intPtrToPtr (fromIntegral esp) :: Ptr CUInt + let ret_ptr = intPtrToPtr (fromIntegral esp) :: Ptr CPtrdiff ret <- peek ret_ptr retval <- peek (intPtrToPtr (fromIntegral (ret - 1)) :: Ptr CUChar) return $ fromIntegral retval -offsetOfCallInsn32 :: CUInt -> IO CUInt +offsetOfCallInsn32 :: CPtrdiff -> IO CPtrdiff offsetOfCallInsn32 esp = do - let ret_ptr = intPtrToPtr (fromIntegral esp) :: Ptr CUInt + let ret_ptr = intPtrToPtr (fromIntegral esp) :: Ptr CPtrdiff ret <- peek ret_ptr peek (intPtrToPtr $ fromIntegral (ret - 4))