--- /dev/null
+module Mate.ClassHierarchy
+ ( isInstanceOf
+ ) where
+
+import qualified Data.ByteString.Lazy as B
+import Control.Applicative
+import Text.Printf
+
+import Mate.NativeSizes
+import Mate.ClassPool
+
+
+data Class
+ = Class
+ { clMtable :: NativeWord
+ , clSuperClass :: Class
+ , clInterfaces :: [Interface]
+ }
+ | JavaLangObject
+ { clMtable :: NativeWord
+ }
+
+data Interface
+ = Interface
+ { ifSuperInterfaces :: [Interface]
+ }
+
+isInstanceOf :: NativeWord -> B.ByteString -> IO Bool
+isInstanceOf obj_mtable classname = do
+ (== obj_mtable) <$> getMethodTable classname
type TrapMap = M.Map NativeWord TrapCause
type TrapPatcher = CPtrdiff -> CodeGen () () CPtrdiff
+type TrapPatcherEax = CPtrdiff -> CPtrdiff -> CodeGen () () CPtrdiff
data TrapCause
= StaticMethod TrapPatcher -- for static calls
| VirtualCall Bool MethodInfo (IO NativeWord) -- for invoke{interface,virtual}
- | InstanceOf B.ByteString -- class name
- | NewObject TrapPatcher -- class name
+ | InstanceOf TrapPatcherEax
+ | NewObject TrapPatcher
| StaticField StaticFieldInfo
| ObjectField TrapPatcher
import Mate.Types
import Mate.Utilities
import Mate.ClassPool
+import Mate.ClassHierarchy
import {-# SOURCE #-} Mate.MethodPool
import Mate.Strings
trapaddr <- getCurrentOffset
-- place something like `mov edx $mtable_of_objref' instead
emit32 (0x9090ffff :: Word32); nop
- cmp eax edx
- sete al
- movzxb eax al
- push eax
- forceRegDump
- return $ Just (trapaddr, InstanceOf $ buildClassID cls cpidx)
+ push (0 :: Word32)
+ let patcher reax reip = do
+ -- mtable <- liftIO $ getMethodTable (buildClassID cls cpidx)
+ -- mov edx mtable
+ emit32 (0x9090ffff :: Word32); nop
+ let classname = buildClassID cls cpidx
+ check <- liftIO $ isInstanceOf (fromIntegral reax) classname
+ if check
+ then push (1 :: Word32)
+ else push (0 :: Word32)
+ return (reip + 5)
+ -- cmp eax edx
+ -- sete al
+ -- movzxb eax al
+ -- push eax
+ -- forceRegDump
+ return $ Just (trapaddr, InstanceOf patcher)
emit' (NEW objidx) = do
let objname = buildClassID cls objidx
trapaddr <- getCurrentOffset
import Foreign
import Foreign.C.Types
-import Harpy
+import Harpy hiding (fst)
import Mate.Types
import Mate.NativeSizes
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 (NewObject patcher)) ->
patchWithHarpy patcher reip >>= delTrue
(Just (VirtualCall False mi io_offset)) ->
if mateDEBUG
then mapM_ (printfJit . printf "patched: %s\n" . showAtt) $ snd right
else return ()
- return reip
+ return $ fst right
withDisasm :: CodeGen e s CPtrdiff -> CodeGen e s (CPtrdiff, [Instruction])
withDisasm patcher = 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