codegen: handle exceptions of a method
[mate.git] / Mate / X86TrapHandling.hs
index 7a5c5494a57f6011b8b9ad45622b3e95a22210c3..82ed7ca0d738ca3ad52b1a0f23562ac8ae0e9597 100644 (file)
@@ -7,12 +7,12 @@ module Mate.X86TrapHandling (
 
 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
@@ -26,9 +26,9 @@ 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
   let reipw32 = fromIntegral reip
   (deleteMe, ret_nreip) <- case M.lookup reipw32 tmap of
@@ -38,8 +38,10 @@ mateHandler reip reax rebx resi = do
         staticFieldHandler reip >>= delTrue
     (Just (ObjectField patcher)) ->
         patchWithHarpy patcher reip >>= delTrue
-    (Just (InstanceOf cn))  ->
-        patchWithHarpy (`patchInstanceOf` cn) reip >>= delFalse
+    (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)) ->
@@ -49,16 +51,14 @@ mateHandler reip reax rebx resi = do
         patchWithHarpy (patchInvoke mi rebx reax io_offset) reip
         >>= delFalse
     Nothing -> case resi of
-        0x13371234 -> return (-1) >>= delFalse
-        _ -> error $ "getTrapType: abort :-( " ++ (showHex reip ". ")
-             ++ (concatMap (`showHex` ", ") (M.keys tmap))
-  if deleteMe
-    then setTrapMap $ M.delete reipw32 tmap
-    else return ()
+        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 = (\nreip -> return (True, nreip))
-    delFalse = (\nreip -> return (False, nreip))
+    where
+      delTrue x = return (True,x)
+      delFalse x = return (False,x)
 
 
 patchWithHarpy :: (CPtrdiff -> CodeGen () () CPtrdiff) -> CPtrdiff -> IO CPtrdiff
@@ -69,10 +69,8 @@ patchWithHarpy patcher reip = do
   let entry = Just (intPtrToPtr (fromIntegral reip), fixme)
   let cgconfig = defaultCodeGenConfig { customCodeBuffer = entry }
   (_, Right right) <- runCodeGenWithConfig (withDisasm $ patcher reip) () () cgconfig
-  if mateDEBUG
-    then mapM_ (printfJit . printf "patched: %s\n" . showAtt) $ snd right
-    else return ()
-  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
@@ -91,19 +89,13 @@ staticFieldHandler reip = do
       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
-
 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
+  vmap <- liftIO getVirtualMap
   let newmi = MethodInfo methname (vmap M.! fromIntegral method_table) msig
   offset <- liftIO io_offset
-  entryAddr <- liftIO $ getMethodEntry newmi
-  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