-{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ForeignFunctionInterface #-}
-#include "debug.h"
module Mate.X86TrapHandling (
mateHandler,
register_signal
import Numeric
import qualified Data.Map as M
-import qualified Data.ByteString.Lazy as B
+import Control.Monad
import Foreign
import Foreign.C.Types
-import Harpy
+import Harpy hiding (fst)
import Mate.Types
import Mate.NativeSizes
import Mate.ClassPool
import Mate.X86CodeGen
-#ifdef DBG_JIT
-import Text.Printf
-#endif
import Mate.Debug
import Harpy.X86Disassembler
foreign import ccall "register_signal"
register_signal :: IO ()
-foreign export ccall mateHandler :: CPtrdiff -> CPtrdiff -> CPtrdiff -> CPtrdiff -> IO CPtrdiff
-mateHandler :: CPtrdiff -> CPtrdiff -> CPtrdiff -> CPtrdiff -> IO CPtrdiff
-mateHandler reip reax rebx resi = do
+foreign export ccall mateHandler :: CPtrdiff -> CPtrdiff -> CPtrdiff -> CPtrdiff -> CPtrdiff -> IO CPtrdiff
+mateHandler :: CPtrdiff -> CPtrdiff -> CPtrdiff -> CPtrdiff -> CPtrdiff -> IO CPtrdiff
+mateHandler reip reax rebx resi resp = do
tmap <- getTrapMap
- case M.lookup (fromIntegral reip) tmap of
- (Just (StaticMethod _)) -> patchWithHarpy patchStaticCall reip
- (Just (StaticField _)) -> staticFieldHandler reip
- (Just (InstanceOf cn)) -> patchWithHarpy (`patchInstanceOf` cn) reip
- (Just (NewObject cn)) -> patchWithHarpy (`patchNewObject` cn) reip
- (Just (VirtualCall False _ io_offset)) ->
- patchWithHarpy (patchInvoke reax reax io_offset) reip
- (Just (VirtualCall True _ io_offset)) ->
- patchWithHarpy (patchInvoke rebx reax io_offset) reip
+ let reipw32 = fromIntegral reip
+ (deleteMe, ret_nreip) <- case M.lookup reipw32 tmap of
+ (Just (StaticMethod patcher)) ->
+ patchWithHarpy patcher reip >>= delFalse
+ (Just (StaticField _)) ->
+ staticFieldHandler reip >>= delTrue
+ (Just (ObjectField patcher)) ->
+ patchWithHarpy patcher reip >>= delTrue
+ (Just (InstanceOf patcher)) ->
+ patchWithHarpy (patcher reax) reip >>= delFalse
+ (Just (ThrowException patcher)) ->
+ patchWithHarpy (patcher reax resp) reip >>= delFalse
+ (Just (NewObject patcher)) ->
+ patchWithHarpy patcher reip >>= delTrue
+ (Just (VirtualCall False mi io_offset)) ->
+ patchWithHarpy (patchInvoke mi reax reax io_offset) reip
+ >>= delFalse
+ (Just (VirtualCall True mi io_offset)) ->
+ patchWithHarpy (patchInvoke mi rebx reax io_offset) reip
+ >>= delFalse
Nothing -> case resi of
- 0x13371234 -> return (-1)
- _ -> error $ "getTrapType: abort :-( " ++ (showHex reip ". ")
- ++ (concatMap (`showHex` ", ") (M.keys tmap))
+ 0x13371234 -> delFalse (-1)
+ _ -> error $ "getTrapType: abort :-( eip: "
+ ++ showHex reip ". " ++ concatMap (`showHex` ", ") (M.keys tmap)
+ when deleteMe $ setTrapMap $ M.delete reipw32 tmap
+ return ret_nreip
+ where
+ delTrue x = return (True,x)
+ delFalse x = return (False,x)
+
patchWithHarpy :: (CPtrdiff -> CodeGen () () CPtrdiff) -> CPtrdiff -> IO CPtrdiff
patchWithHarpy patcher reip = do
let entry = Just (intPtrToPtr (fromIntegral reip), fixme)
let cgconfig = defaultCodeGenConfig { customCodeBuffer = entry }
(_, Right right) <- runCodeGenWithConfig (withDisasm $ patcher reip) () () cgconfig
- mapM_ (printfJit "patched: %s\n" . showAtt) $ snd right
- return reip
+ when mateDEBUG $ mapM_ (printfJit . printf "patched: %s\n" . showIntel) $ snd right
+ return $ fst right
withDisasm :: CodeGen e s CPtrdiff -> CodeGen e s (CPtrdiff, [Instruction])
withDisasm patcher = do
d <- disassemble
return (reip, d)
-patchStaticCall :: CPtrdiff -> CodeGen e s CPtrdiff
-patchStaticCall reip = do
- entryAddr <- liftIO $ getMethodEntry reip 0
- call (fromIntegral (entryAddr - (reip + 5)) :: NativeWord)
- return reip
-
-
staticFieldHandler :: CPtrdiff -> IO CPtrdiff
staticFieldHandler reip = do
-- patch the offset here, first two bytes are part of the insn (opcode + reg)
return reip
else error "staticFieldHandler: something is wrong here. abort.\n"
-patchInstanceOf :: CPtrdiff -> B.ByteString -> CodeGen e s CPtrdiff
-patchInstanceOf reip classname = do
- mtable <- liftIO $ getMethodTable classname
- mov edx mtable
- return reip
-
-patchNewObject :: CPtrdiff -> B.ByteString -> CodeGen e s CPtrdiff
-patchNewObject reip classname = do
- objsize <- liftIO $ getObjectSize classname
- push32 objsize
- callMalloc
- mtable <- liftIO $ getMethodTable classname
- mov (Disp 0, eax) mtable
- return reip
-
-patchInvoke :: CPtrdiff -> CPtrdiff -> IO NativeWord -> CPtrdiff -> CodeGen e s CPtrdiff
-patchInvoke method_table table2patch io_offset reip = do
+patchInvoke :: MethodInfo -> CPtrdiff -> CPtrdiff -> IO NativeWord -> CPtrdiff -> CodeGen e s CPtrdiff
+patchInvoke (MethodInfo methname _ msig) method_table table2patch io_offset reip = do
+ vmap <- liftIO getVirtualMap
+ let newmi = MethodInfo methname (vmap M.! fromIntegral method_table) msig
offset <- liftIO io_offset
- entryAddr <- liftIO $ getMethodEntry reip method_table
- call32_eax (Disp offset)
+ (entryAddr, _) <- liftIO $ getMethodEntry newmi
+ call32Eax (Disp offset)
-- patch entry in table
let call_insn = intPtrToPtr . fromIntegral $ table2patch + fromIntegral offset
liftIO $ poke call_insn entryAddr