Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite StackMapTable solver #1

Merged
merged 23 commits into from
Dec 7, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix incorrect stack changes for InvokeX
bristermitten committed Dec 5, 2023
commit f74885eb98abf374bb8bcf7e898b82bbfa48e7e3
9 changes: 4 additions & 5 deletions src/JVM/Data/Abstract/Descriptor.hs
Original file line number Diff line number Diff line change
@@ -4,16 +4,15 @@ import Data.Data
import JVM.Data.Abstract.Type (FieldType)
import JVM.Data.Pretty

data MethodDescriptor
= MethodDescriptor [FieldType] ReturnDescriptor
data MethodDescriptor = MethodDescriptor
{ params :: [FieldType]
, return :: ReturnDescriptor
}
deriving (Show, Eq, Ord, Data)

instance Pretty MethodDescriptor where
pretty (MethodDescriptor params ret) = "(" <> hsep (pretty <$> params) <> ")" <> pretty ret

methodParams :: MethodDescriptor -> [FieldType]
methodParams (MethodDescriptor params _) = params

methodParam :: MethodDescriptor -> Int -> Maybe FieldType
methodParam (MethodDescriptor params _) i = params !!? i
where
17 changes: 8 additions & 9 deletions src/JVM/Data/Analyse/StackMap.hs
Original file line number Diff line number Diff line change
@@ -10,11 +10,11 @@ module JVM.Data.Analyse.StackMap where
import Control.Lens.Fold
import Data.Generics.Sum (AsAny (_As))
import Data.List
import Data.Maybe (fromJust)
import Data.Maybe (fromJust, maybeToList)
import GHC.Stack (HasCallStack)
import JVM.Data.Abstract.Builder.Label
import JVM.Data.Abstract.ClassFile.Method
import JVM.Data.Abstract.Descriptor (MethodDescriptor (MethodDescriptor), methodParams)
import JVM.Data.Abstract.Descriptor (MethodDescriptor (..), returnDescriptorType)
import JVM.Data.Abstract.Instruction
import JVM.Data.Abstract.Type (FieldType (..), PrimitiveType (..), fieldTypeToClassInfoType)

@@ -55,7 +55,7 @@ splitIntoBasicBlocks l =
splitOnLabels :: [Instruction] -> [(Maybe Label, [Instruction])]
splitOnLabels xs = go xs []
where
go :: [Instruction] -> ([Instruction]) -> [(Maybe Label, [Instruction])]
go :: [Instruction] -> [Instruction] -> [(Maybe Label, [Instruction])]
go [] acc = [(Nothing, acc)]
go (x : xs) acc = case x ^? _As @"Label" of
Just l' -> (Just l', acc) : go xs []
@@ -65,8 +65,7 @@ topFrame :: MethodDescriptor -> Frame
topFrame (MethodDescriptor args _) = Frame (map LocalVariable args) []

analyseBlockDiff :: Frame -> BasicBlock -> Frame
analyseBlockDiff current block = do
foldl (flip analyseInstruction) current (takeWhileInclusive (not . isConditionalJump) block.instructions)
analyseBlockDiff current block = foldl (flip analyseInstruction) current (takeWhileInclusive (not . isConditionalJump) block.instructions)
where
isConditionalJump :: Instruction -> Bool
isConditionalJump (IfEq _) = True
@@ -94,10 +93,10 @@ analyseBlockDiff current block = do
analyseInstruction (IfGe _) ba = ba{stack = tail ba.stack}
analyseInstruction (IfGt _) ba = ba{stack = tail ba.stack}
analyseInstruction (IfLe _) ba = ba{stack = tail ba.stack}
analyseInstruction (InvokeStatic _ _ md) ba = ba{stack = drop (length (methodParams md)) ba.stack}
analyseInstruction (InvokeVirtual _ _ md) ba = ba{stack = drop (1 + length (methodParams md)) ba.stack}
analyseInstruction (InvokeInterface _ _ md) ba = ba{stack = drop (1 + length (methodParams md)) ba.stack}
analyseInstruction (InvokeDynamic _ _ md) ba = ba{stack = drop (1 + length (methodParams md)) ba.stack}
analyseInstruction (InvokeStatic _ _ md) ba = ba{stack = (StackEntry <$> maybeToList (returnDescriptorType md.return)) <> drop (length md.params) ba.stack}
analyseInstruction (InvokeVirtual _ _ md) ba = ba{stack = (StackEntry <$> maybeToList (returnDescriptorType md.return)) <> drop (1 + length md.params) ba.stack}
analyseInstruction (InvokeInterface _ _ md) ba = ba{stack = (StackEntry <$> maybeToList (returnDescriptorType md.return)) <> drop (length md.params) ba.stack}
analyseInstruction (InvokeDynamic _ _ md) ba = ba{stack = (StackEntry <$> maybeToList (returnDescriptorType md.return)) <> drop (1 + length md.params) ba.stack}
analyseInstruction other ba = error $ "Instruction not supported: " <> show other

frameDiffToSMF :: (HasCallStack) => Frame -> BasicBlock -> StackMapFrame