{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell, FlexibleInstances #-} module Main where import Data.Binary import Data.String import System.Environment hiding (getEnv) import qualified Data.Map as M import qualified Data.ByteString.Lazy as B import Text.Printf import Control.Monad import qualified JVM.Assembler as J import JVM.Assembler hiding (Instruction) import JVM.Common import JVM.ClassFile import JVM.Converter import JVM.Dump import Foreign import Harpy import Harpy.X86Disassembler $(callDecl "callAsWord32" [t|Word32|]) main = do args <- getArgs case args of [clspath] -> do clsFile <- decodeFile clspath let cp = constsPool (clsFile :: Class Pointers) putStrLn "==== constpool: ====" putStrLn $ showListIx $ M.elems cp cf <- parseClassFile clspath putStrLn "==== classfile dump: ====" dumpClass cf putStrLn "==== random stuff: ====" let mainmethod = lookupMethod "main" cf -- "main|([Ljava/lang/String;)V" cf case mainmethod of Nothing -> putStrLn "no main found" Just main -> case attrByName main "Code" of Nothing -> putStrLn "no code attr found" Just bytecode -> do putStrLn "woot, running now" allocaArray 26 (\ p -> mapM_ (\ i -> poke (advancePtr p i) 0) [0..25] >> runstuff p bytecode) _ -> error "Synopsis: dump-class File.class" runstuff :: Ptr Int32 -> B.ByteString -> IO () runstuff env bytecode = do (_, Right (ret, disasm)) <- runCodeGen (compile $ codeInstructions $ decodeMethod bytecode) env () printf "return value: 0x%08x\n" ret printf "disasm:\n" mapM_ (putStrLn . showAtt) disasm return () entryCode :: CodeGen e s () entryCode = do push ebp mov ebp esp exitCode :: CodeGen e s () exitCode = do mov esp ebp pop ebp ret compile :: [J.Instruction] -> CodeGen (Ptr Int32) s (Int32, [Instruction]) compile insn = do entryCode mapM compile_ins insn exitCode d <- disassemble r <- callAsWord32 return (fromIntegral r, d) compile_ins :: J.Instruction -> CodeGen (Ptr Int32) s () compile_ins (BIPUSH w8) = do mov eax ((fromIntegral w8) :: Word32) compile_ins (PUTSTATIC w16) = do nop compile_ins (GETSTATIC w16) = do nop compile_ins ICONST_2 = do nop compile_ins IMUL = do nop compile_ins RETURN = do nop compile_ins _ = do nop -- TODO: actually this function already exists in hs-java-0.3! lookupMethod :: B.ByteString -> Class Resolved -> Maybe (Method Resolved) lookupMethod name cls = look (classMethods cls) where look [] = Nothing look (f:fs) | methodName f == name = Just f | otherwise = look fs