<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">2015-08-30 5:46 GMT+02:00 Kim-Ee Yeoh <span dir="ltr"><<a href="mailto:ky3@atamo.com" target="_blank">ky3@atamo.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><span class=""><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Aug 30, 2015 at 6:12 AM, Gautier DI FOLCO <span dir="ltr"><<a href="mailto:gautier.difolco@gmail.com" target="_blank">gautier.difolco@gmail.com</a>></span> wrote:<br><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">I have two main goals:<br> * print the signification of each bytecodes (a more explicit one than the hexadecimal value of the bytecode)<br> * Do some analysis on it, spot patterns, apply markov model on it and so on.</div></blockquote></div><br></div></span><div class="gmail_extra">Work backwards, a piece at a time.<br></div><div class="gmail_extra"><br></div><div class="gmail_extra">The output of parsing is a piece of structured data. So you need to design your data type. Start with the bare minimum. Write the pretty printing code. What do the type signatures of your analysis functions look like? <br><br>E.g. "Apply markov model" is way too vague. <br><br>The key thing is to iterate and improve on the design of your data type.<br><br></div><div class="gmail_extra">Once the data type looks good, the implementation of parsing becomes clear as day.<span class=""><font color="#888888"><br></font></span></div><span class=""><font color="#888888"><div class="gmail_extra"><br clear="all"><div><div>-- Kim-Ee</div></div>
</div></font></span></div>
</blockquote></div><br>Hello,<br><br>Thanks for your answer.<br>I think I have misled you in the expression of my needs.<br>I don't have any representation issues, I'm just looking for a good design for the parsing phase.<br>Here's some naive iterative tries:<br>0. We only have one bytecode per instruction a simple HashMap is enough:<br><div style="margin-left:40px">import Data.Word<br>import Data.Maybe<br>import qualified Data.Map as H<br>type Byte = Word8<br><br>data ByteCodeSimpleInstruction =<br>      Astore_0 -- 0x4B<br>    | Astore_1 -- 0x4C<br>    | Astore_2 -- 0x4D<br>    | Astore_3 -- 0x4E<br>    deriving (Eq, Show)<br><br>sampleSI :: [Byte]<br>sampleSI = [0x4B, 0x4C, 0x4D, 0x4E]<br><br>convertTableSI :: H.Map Byte ByteCodeSimpleInstruction<br>convertTableSI = H.fromList $ [<br>      (0x4B, Astore_0),<br>      (0x4C, Astore_1),<br>      (0x4D, Astore_2),<br>      (0x4E, Astore_3)<br>    ]<br><br>parserSI :: [Byte] -> [ByteCodeSimpleInstruction]<br>parserSI = map $ fromJust . flip H.lookup convertTableSI<br></div><br>1. We add instruction with different lengths, I'm "forced" to introduce pattern matching and it makes me sad:<br><div style="margin-left:40px">data ByteCodeVariableLengthInstruction =<br>      Astore' Byte -- 0x19<br>    | Astore_0' -- 0x4B<br>    | Astore_1' -- 0x4C<br>    | Astore_2' -- 0x4D<br>    | Astore_3' -- 0x4E<br>    deriving (Eq, Show)<br><br>sampleVLI :: [Byte]<br>sampleVLI = [0x4B, 0x4C, 0x19, 0x2A, 0x4D, 0x4E]<br><br>parserVLI :: [Byte] -> [ByteCodeVariableLengthInstruction]<br>parserVLI b = case b of<br>    (0x19:p:n) -> (Astore' p):parserVLI n<br>    (0x4B:n)   -> Astore_0':parserVLI n<br>    (0x4C:n)   -> Astore_1':parserVLI n<br>    (0x4D:n)   -> Astore_2':parserVLI n<br>    (0x4E:n)   -> Astore_3':parserVLI n<br>    []         -> []<br></div><br>2. We add instructions that change the next instruction's length, we are "forced" to add different parsing strategies:<br><div style="margin-left:40px">data ByteCodeVariableLengthParameterInstruction =<br>      Astore'' ByteParameter -- 0x19<br>    | Astore_0'' -- 0x4B<br>    | Astore_1'' -- 0x4C<br>    | Astore_2'' -- 0x4D<br>    | Astore_3'' -- 0x4E<br>    | Wide'' -- 0xDD<br>    deriving (Eq, Show)<br><br>data ByteParameter =<br>      Simple Byte<br>    | Double Byte Byte<br>    deriving (Eq, Show)<br><br>sampleVLPI :: [Byte]<br>sampleVLPI = [0x4B, 0x4C, 0xDD, 0x19, 0xA2, 0x2A, 0x4D, 0x4E]<br><br>parserVLPI :: [Byte] -> [ByteCodeVariableLengthParameterInstruction]<br>parserVLPI = parserVLPISimple<br><br>parserVLPISimple :: [Byte] -> [ByteCodeVariableLengthParameterInstruction]<br>parserVLPISimple b = case b of<br>    (0x19:p:n) -> (Astore'' (Simple p)):parserVLPISimple n<br>    (0x4B:n)   -> Astore_0'':parserVLPISimple n<br>    (0x4C:n)   -> Astore_1'':parserVLPISimple n<br>    (0x4D:n)   -> Astore_2'':parserVLPISimple n<br>    (0x4E:n)   -> Astore_3'':parserVLPISimple n<br>    (0xDD:n)   -> Wide'':parserVLPIDouble n<br>    []         -> []<br><br>parserVLPIDouble :: [Byte] -> [ByteCodeVariableLengthParameterInstruction]<br>parserVLPIDouble b = case b of<br>    (0x19:p:q:n) -> (Astore'' (Double p q)):parserVLPISimple n<br>    _            -> parserVLPISimple b<br></div><br><br>I feel that are too "ad-hoc" tactics and I'm looking for an higher-order way to do it.<br>I don't know if I'm clearer now.<br><br>Thanks in advance for you help.<br>Regards.<br><br>PS: For the Markov part, Markov models will help me to spot the most common sequences of bytecodes. Then I'll be able to create proprietary byte that will be the most likely to decrease my code's size.<br></div></div>