From e7e935029c53fe5a46b6153e4fca74d4994459ff Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Tue, 24 Apr 2012 11:10:42 +0200 Subject: [PATCH] static methods: add inheritance capability if the method isn't found when compiling, check the superclasses for this certain method. if one is found eventually, add an map entry for each class to the same method entry. see tests/Static5.java --- Makefile | 2 ++ Mate.hs | 4 +++- Mate/MethodPool.hs | 51 +++++++++++++++++++++++++++++++++------------- tests/Static5.java | 13 ++++++++++++ 4 files changed, 55 insertions(+), 15 deletions(-) create mode 100644 tests/Static5.java diff --git a/Makefile b/Makefile index 38fee44..74652f5 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,8 @@ test: mate $(CLASS_FILES) @printf "should be: 0x%08x\n" 0x6dd ./$< tests/Static4 | grep mainresult @printf "should be: 0x%08x 0x%08x\n" 0x33 0x77 + ./$< tests/Static5 | grep mainresult + @printf "should be: 0x%08x 0x%08x\n" 0x33 0x33 ./$< tests/CallConv1 | grep mainresult @printf "should be: 0x%08x\n" 0x1337 ./$< tests/CallConv2 | grep mainresult diff --git a/Mate.hs b/Mate.hs index 946b692..eb7c765 100644 --- a/Mate.hs +++ b/Mate.hs @@ -35,7 +35,9 @@ main = do let method = find (\x -> (methodName x) == "main") methods case method of Just m -> do - entry <- compileBB hmap' (MethodInfo "main" bclspath (methodSignature m)) + let mi = (MethodInfo "main" bclspath (methodSignature m)) + entry <- compileBB hmap' mi + addMethodRef entry mi [bclspath] printf "executing `main' now:\n" executeFuncPtr entry Nothing -> error "main not found" diff --git a/Mate/MethodPool.hs b/Mate/MethodPool.hs index c76cf91..811d1fb 100644 --- a/Mate/MethodPool.hs +++ b/Mate/MethodPool.hs @@ -6,6 +6,7 @@ import Data.Binary import Data.String.Utils import qualified Data.Map as M import qualified Data.Set as S +import qualified Data.ByteString.Lazy as B import System.Plugins import Text.Printf @@ -44,18 +45,19 @@ getMethodEntry signal_from ptr_mmap ptr_tmap = do Nothing -> do cls <- getClassFile cm printf "getMethodEntry(from 0x%08x): no method \"%s\" found. compile it\n" w32_from (show mi') - let mm = lookupMethod method cls + mm <- lookupMethodRecursive method [] cls case mm of - Just mm' -> do + Just (mm', clsnames, cls') -> do let flags = methodAccessFlags mm' case S.member ACC_NATIVE flags of False -> do - hmap <- parseMethod cls method + hmap <- parseMethod cls' method printMapBB hmap case hmap of Just hmap' -> do - entry <- compileBB hmap' mi' - return $ fromIntegral $ ((fromIntegral $ ptrToIntPtr entry) :: Word32) + entry <- compileBB hmap' (MethodInfo method (thisClass cls') sig) + addMethodRef entry mi' clsnames + return $ fromIntegral entry Nothing -> error $ (show method) ++ " not found. abort" True -> do let symbol = (replace "/" "_" $ toString cm) ++ "__" ++ (toString method) ++ "__" ++ (replace "(" "_" (replace ")" "_" $ toString $ encode sig)) @@ -69,6 +71,22 @@ getMethodEntry signal_from ptr_mmap ptr_tmap = do Just w32 -> return (fromIntegral w32) _ -> error $ "getMethodEntry: no trapInfo. abort" +lookupMethodRecursive :: B.ByteString -> [B.ByteString] -> Class Resolved + -> IO (Maybe ((Method Resolved, [B.ByteString], Class Resolved))) +lookupMethodRecursive name clsnames cls = do + case res of + Just x -> return $ Just (x, nextclsn, cls) + Nothing -> if thisname == "java/lang/Object" + then return $ Nothing + else do + supercl <- getClassFile (superClass cls) + lookupMethodRecursive name nextclsn supercl + where + res = lookupMethod name cls + thisname = thisClass cls + nextclsn :: [B.ByteString] + nextclsn = thisname:clsnames + -- TODO(bernhard): UBERHAX. ghc patch? foreign import ccall safe "lookupSymbol" c_lookupSymbol :: CString -> IO (Ptr a) @@ -98,20 +116,24 @@ initMethodPool = do tmap2ptr M.empty >>= set_trapmap classmap2ptr M.empty >>= set_classmap -compileBB :: MapBB -> MethodInfo -> IO (Ptr Word8) -compileBB hmap methodinfo = do + +addMethodRef :: Word32 -> MethodInfo -> [B.ByteString] -> IO () +addMethodRef entry mi@(MethodInfo mname _ msig) clsnames = do mmap <- get_methodmap >>= ptr2mmap + let newmap = M.fromList $ map (\x -> ((MethodInfo mname x msig), entry)) clsnames + let mmap' = newmap `M.union` newmap + mmap2ptr mmap' >>= set_methodmap + + +compileBB :: MapBB -> MethodInfo -> IO Word32 +compileBB hmap methodinfo = do tmap <- get_trapmap >>= ptr2tmap - -- TODO(bernhard): replace parsing with some kind of classpool cls <- getClassFile (cName methodinfo) let ebb = emitFromBB (methName methodinfo) cls hmap (_, Right ((entry, _, _, new_tmap), disasm)) <- runCodeGen ebb () () - let w32_entry = ((fromIntegral $ ptrToIntPtr entry) :: Word32) - let mmap' = M.insert methodinfo w32_entry mmap let tmap' = M.union tmap new_tmap -- prefers elements in cmap - mmap2ptr mmap' >>= set_methodmap tmap2ptr tmap' >>= set_trapmap printf "disasm:\n" @@ -122,8 +144,9 @@ compileBB hmap methodinfo = do -- (2) on getLine, press ctrl+c -- (3) `br *0x'; obtain the address from the disasm above -- (4) `cont' and press enter - return entry + return $ fromIntegral $ ptrToIntPtr entry -executeFuncPtr :: Ptr Word8 -> IO () -executeFuncPtr entry = code_void $ ((castPtrToFunPtr entry) :: FunPtr (IO ())) +executeFuncPtr :: Word32 -> IO () +executeFuncPtr entry = + code_void $ ((castPtrToFunPtr $ intPtrToPtr $ fromIntegral entry) :: FunPtr (IO ())) diff --git a/tests/Static5.java b/tests/Static5.java new file mode 100644 index 0000000..14c41d4 --- /dev/null +++ b/tests/Static5.java @@ -0,0 +1,13 @@ +package tests; + +public class Static5 extends Static1 { + public static int x; + public static int y; + + public static void main(String []args) { + Static5.setNumbers(); + Static5.addNumbers(); // 0x33 + Static1.addNumbers(); // 0x33 + // System.out.printf("%x\n", Static5.addNumbers()); + } +} -- 2.25.1