all: mate $(CLASS_FILES)
test: mate $(CLASS_FILES)
- ./$< tests/Fib.class
- ./$< tests/Fac.class
+ ./$< tests/Fib.class | grep mainresult
+ @printf "should be: 0x%08x\n" 0x09de8d6d
+ ./$< tests/Fac.class | grep mainresult
+ @printf "should be: 0x%08x\n" 0x58980
+ ./$< tests/ArgumentPassing1.class | grep mainresult
+ @printf "should be: 0x%08x\n" 0x92
+ @printf "should be: 0x%08x\n" $$(((0 - 0x1337) & 0xffffffff))
%.class: %.java
$(JAVAC) $<
dot :: B.ByteString
-- TODO(bernhard): WTF? why -XOverloadedStrings doesn't apply here?
dot = B.pack $ map (fromIntegral . ord) "."
+
+methodGetArgsCount :: Class Resolved -> Word16 -> Word32
+methodGetArgsCount cls idx = fromIntegral $ length args
+ where
+ (CMethod _ nt) = (constsPool cls) M.! idx
+ (MethodSignature args _) = ntSignature nt
+
+-- TODO(bernhard): Extend it to more than just int, and provide typeinformation
+methodHaveReturnValue :: Class Resolved -> Word16 -> Bool
+methodHaveReturnValue cls idx = case ret of
+ ReturnsVoid -> False;
+ (Returns IntType) -> True;
+ _ -> error "methodHaveReturnValue: todo"
+ where
+ (CMethod _ nt) = (constsPool cls) M.! idx
+ (MethodSignature _ ret) = ntSignature nt
import Data.Maybe
import qualified Data.Map as M
import qualified Data.ByteString.Lazy as B
+import Control.Monad
import Foreign
import Foreign.C.Types
-- causes SIGILL. in the signal handler we patch it to the acutal call.
-- place a nop at the end, therefore the disasm doesn't screw up
emit32 (0xffffffff :: Word32) >> emit8 (0x90 :: Word8)
- -- discard arguments (TODO(bernhard): don't hardcode it)
- add esp (4 :: Word32)
- -- push result on stack (TODO(bernhard): if any)
- push eax
+ -- discard arguments on stack
+ let argcnt = (methodGetArgsCount cls cpidx) * 4
+ when (argcnt > 0) (add esp argcnt)
+ -- push result on stack if method has a return value
+ when (methodHaveReturnValue cls cpidx) (push eax)
return $ Just $ (w32_calladdr, (l, cls, cpidx))
emit' insn = emit insn >> return Nothing
call (trapaddr - w32_calladdr)
add esp (4 :: Word32)
emit (BIPUSH val) = push ((fromIntegral val) :: Word32)
+ emit (SIPUSH val) = push ((fromIntegral $ ((fromIntegral val) :: Int16)) :: Word32)
emit (ICONST_0) = push (0 :: Word32)
emit (ICONST_1) = push (1 :: Word32)
emit (ICONST_2) = push (2 :: Word32)
+ emit (ICONST_4) = push (4 :: Word32)
emit (ICONST_5) = push (5 :: Word32)
emit (ILOAD_ x) = do
push (Disp (cArgs_ x), ebp)
--- /dev/null
+package tests;
+
+public class ArgumentPassing1 {
+ public static void main(String []args) {
+ myadder(23, 4, 0x77); // 0x92
+ noreturn(23, 4, 0x77); // nothing
+ noargs(); // 0x1337
+ }
+
+ public static int myadder(int a, int b, int c) {
+ return a + b + c;
+ }
+
+ public static void noreturn(int a, int b, int c) {
+ return;
+ }
+
+ public static int noargs() {
+ return -0x1337;
+ }
+}