From b6e379114b45fca215e766816e9db94199bb4f00 Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Wed, 25 Apr 2012 11:03:06 +0200 Subject: [PATCH] fields: use offsets from ClassInfo in codegen BUT: Couldn't match expected type `IO CUInt' against inferred type `CodeGen e s CUInt' any idea how to solve this problem *without* `unsafePerformIO'? --- Makefile | 2 ++ Mate/ClassPool.hs | 18 +++++++++++------- Mate/Utilities.hs | 8 ++++++-- Mate/X86CodeGen.hs | 12 ++++++++---- ffi/trap.c | 4 ++-- tests/Instance1.java | 1 + tests/Instance2.java | 23 +++++++++++++++++++++++ 7 files changed, 53 insertions(+), 15 deletions(-) create mode 100644 tests/Instance2.java diff --git a/Makefile b/Makefile index 3930089..3c004ec 100644 --- a/Makefile +++ b/Makefile @@ -50,6 +50,8 @@ test: mate $(CLASS_FILES) @printf "should be: 0x%08x\n" 0x1337 ./$< tests/Instance1 | grep mainresult @printf "should be: 0x%08x 0x%08x\n" 0x55 0x11 + ./$< tests/Instance2 | grep mainresult + @printf "should be: 0x%08x\n" 0x198 %.class: %.java $(JAVAC) $< diff --git a/Mate/ClassPool.hs b/Mate/ClassPool.hs index be4af60..44ff8ac 100644 --- a/Mate/ClassPool.hs +++ b/Mate/ClassPool.hs @@ -3,9 +3,11 @@ module Mate.ClassPool ( getClassInfo, getClassFile, - getFieldAddr + getFieldOffset, + getStaticFieldAddr ) where +import Data.Int import qualified Data.Map as M import qualified Data.Set as S import qualified Data.ByteString.Lazy as B @@ -42,14 +44,14 @@ getStaticFieldOffset path field = do ci <- getClassInfo path return $ fromIntegral $ (clStaticMap ci) M.! field -getFieldOffset :: B.ByteString -> B.ByteString -> IO (CUInt) +getFieldOffset :: B.ByteString -> B.ByteString -> IO (Int32) getFieldOffset path field = do ci <- getClassInfo path - return $ fromIntegral $ (clFieldMap ci) M.! field + return $ (clFieldMap ci) M.! field -foreign export ccall getFieldAddr :: CUInt -> Ptr () -> IO CUInt -getFieldAddr :: CUInt -> Ptr () -> IO CUInt -getFieldAddr from ptr_trapmap = do +foreign export ccall getStaticFieldAddr :: CUInt -> Ptr () -> IO CUInt +getStaticFieldAddr :: CUInt -> Ptr () -> IO CUInt +getStaticFieldAddr from ptr_trapmap = do trapmap <- ptr2tmap ptr_trapmap let w32_from = fromIntegral from let sfi = trapmap M.! w32_from @@ -93,8 +95,10 @@ calculateFields cf superclass = do -- new fields "overwrite" old ones, if they have the same name let staticmap = (M.fromList sm) `M.union` sc_sm - let im = zipbase 0 ifields let sc_im = getsupermap clFieldMap + -- TODO(bernhard): not efficient :-( + let max_off = if (M.size sc_im) > 0 then maximum $ M.elems sc_im else 0 + let im = zipbase (max_off + 4) ifields -- new fields "overwrite" old ones, if they have the same name let fieldmap = (M.fromList im) `M.union` sc_im diff --git a/Mate/Utilities.hs b/Mate/Utilities.hs index 2d755cc..7a75466 100644 --- a/Mate/Utilities.hs +++ b/Mate/Utilities.hs @@ -24,8 +24,12 @@ buildMethodID cls idx = MethodInfo (ntName nt) rc (ntSignature nt) where (CMethod rc nt) = (constsPool cls) M.! idx -buildFieldID :: Class Resolved -> Word16 -> StaticFieldInfo -buildFieldID cls idx = StaticFieldInfo rc (ntName fnt) +buildStaticFieldID :: Class Resolved -> Word16 -> StaticFieldInfo +buildStaticFieldID cls idx = StaticFieldInfo rc (ntName fnt) + where (CField rc fnt) = (constsPool cls) M.! idx + +buildFieldOffset :: Class Resolved -> Word16 -> (B.ByteString, B.ByteString) +buildFieldOffset cls idx = (thisClass cls, ntName fnt) where (CField rc fnt) = (constsPool cls) M.! idx methodGetArgsCount :: Class Resolved -> Word16 -> Word32 diff --git a/Mate/X86CodeGen.hs b/Mate/X86CodeGen.hs index 3f8e6f4..57ffdff 100644 --- a/Mate/X86CodeGen.hs +++ b/Mate/X86CodeGen.hs @@ -188,12 +188,12 @@ emitFromBB method cls hmap = do pop eax trapaddr <- getCurrentOffset mov (Addr 0x00000000) eax -- it's a trap - return $ Just $ (trapaddr, SFI $ buildFieldID cls cpidx) + return $ Just $ (trapaddr, SFI $ buildStaticFieldID cls cpidx) emit' (GETSTATIC cpidx) = do trapaddr <- getCurrentOffset mov eax (Addr 0x00000000) -- it's a trap push eax - return $ Just $ (trapaddr, SFI $ buildFieldID cls cpidx) + return $ Just $ (trapaddr, SFI $ buildStaticFieldID cls cpidx) emit' insn = emit insn >> return Nothing emit :: J.Instruction -> CodeGen e s () @@ -240,11 +240,15 @@ emitFromBB method cls hmap = do emit (GETFIELD x) = do pop eax -- this pointer - push (Disp (fromIntegral x * 4), eax) -- get field + let (cname, fname) = buildFieldOffset cls x + let offset = unsafePerformIO $ getFieldOffset cname fname + push (Disp (fromIntegral $ offset * 4), eax) -- get field emit (PUTFIELD x) = do pop ebx -- value to write pop eax -- this pointer - mov (Disp (fromIntegral x * 4), eax) ebx -- set field + let (cname, fname) = buildFieldOffset cls x + let offset = unsafePerformIO $ getFieldOffset cname fname + mov (Disp (fromIntegral $ offset * 4), eax) ebx -- set field emit IADD = do pop ebx; pop eax; add eax ebx; push eax emit ISUB = do pop ebx; pop eax; sub eax ebx; push eax diff --git a/ffi/trap.c b/ffi/trap.c index 3671710..a2af970 100644 --- a/ffi/trap.c +++ b/ffi/trap.c @@ -17,7 +17,7 @@ #include unsigned int getMethodEntry(unsigned int, void *, void *); -unsigned int getFieldAddr(unsigned int, void*); +unsigned int getStaticFieldAddr(unsigned int, void*); #define NEW_MAP(prefix) \ void* prefix ## _map = NULL; \ @@ -74,7 +74,7 @@ void staticfieldtrap(int nSignal, siginfo_t *info, void *ctx) printf("staticfieldtrap: something is wrong here. abort\n"); exit(0); } - unsigned int patchme = getFieldAddr(from, trap_map); + unsigned int patchme = getStaticFieldAddr(from, trap_map); printf(" to_patch: 0x%08x\n", (unsigned int) to_patch); printf("*to_patch: 0x%08x\n", *to_patch); diff --git a/tests/Instance1.java b/tests/Instance1.java index c9a90f9..e15505e 100644 --- a/tests/Instance1.java +++ b/tests/Instance1.java @@ -15,6 +15,7 @@ public class Instance1 { } public static int id(int a) { + // System.out.printf("0x%08x\n", a); return a; } } diff --git a/tests/Instance2.java b/tests/Instance2.java new file mode 100644 index 0000000..6f25480 --- /dev/null +++ b/tests/Instance2.java @@ -0,0 +1,23 @@ +package tests; + +public class Instance2 extends Instance1 { + public int y; + + public Instance2() { + x = 0x66; + y = 0x77; + } + + public static void main(String []args) { + int sum = 0; + Instance1 a = new Instance1(); + Instance2 b = new Instance2(); + sum += a.x; // 0x55 + sum += b.x; // 0x66 + sum += b.y; // 0x77 + a.x = 0x11; sum += a.x; // 0x11 + b.x = 0x22; sum += b.x; // 0x22 + b.y = 0x33; sum += b.y; // 0x33 + Instance1.id(sum); // 0x198 + } +} -- 2.25.1