staticcall trap: use different magic sequence
authorBernhard Urban <lewurm@gmail.com>
Thu, 2 Aug 2012 19:37:24 +0000 (21:37 +0200)
committerBernhard Urban <lewurm@gmail.com>
Thu, 2 Aug 2012 19:36:57 +0000 (21:36 +0200)
place invalid opcode *before* both NOPs, otherwise two NOP instrunctions are
executed before every actual traphandling stuff (although, CPUs nowadays will
optimize those NOP-sequences away anyways I guess...)

btw, fuuuu @ byte order *sigh*  I'll never get it...

Mate/X86CodeGen.hs
Mate/X86TrapHandling.hs

index 6def8de41da1f5d8bafee84acce33cd413297dda..710b5b60d5a1589adc5c1d7253dd0ef23416ac89 100644 (file)
@@ -104,15 +104,14 @@ emitFromBB cls method = do
       calladdr <- getCurrentOffset
       newNamedLabel (show l) >>= defineLabel
       -- 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 (0xffff9090 :: Word32) >> emit8 (0x90 :: Word8)
+      -- place two nop's at the end, therefore the disasm doesn't screw up
+      emit32 (0x9090ffff :: Word32) >> emit8 (0x90 :: Word8)
       -- discard arguments on stack
       let argcnt = ((if hasThis then 1 else 0) + methodGetArgsCount (methodNameTypeByIdx cls cpidx)) * ptrSize
       when (argcnt > 0) (add esp argcnt)
       -- push result on stack if method has a return value
       when (methodHaveReturnValue cls cpidx) (push eax)
-      -- +2 is for correcting eip in trap context
-      return $ Just (calladdr + 2, StaticMethod l)
+      return $ Just (calladdr, StaticMethod l)
 
     invokeEpilog :: Word16 -> Word32 -> (Bool -> TrapCause) -> CodeGen e s (Maybe (Word32, TrapCause))
     invokeEpilog cpidx offset trapcause = do
index 6ec0124f2c56e9ec347e982d37eeb3e6d6e8c648..f89e2b8f77493ac5b6d3df60b802aaac5688220f 100644 (file)
@@ -51,24 +51,23 @@ mateHandler eip eax ebx esp = do
 
 staticCallHandler :: CPtrdiff -> IO CPtrdiff
 staticCallHandler eip = do
-  -- the actual insn to patch is displaced by two bytes
-  let insn_ptr = intPtrToPtr (fromIntegral (eip - 2)) :: Ptr CUChar
-  -- call offset is displaced by one byte
-  let imm_ptr = intPtrToPtr (fromIntegral (eip - 1)) :: Ptr CPtrdiff
+  -- the actual insn to patch as pointer
+  let insn_ptr = intPtrToPtr (fromIntegral eip) :: Ptr CUChar
+  -- call offset is displaced by one byte (as the first byte is the opcode)
+  let imm_ptr = intPtrToPtr (fromIntegral (eip + 1)) :: Ptr CPtrdiff
   -- in codegen we set the immediate to some magic value
   -- in order to produce a SIGILL signal. we also do a safety
   -- check here, if we're really the "owner" of this signal.
   checkMe <- peek imm_ptr
-  if checkMe == 0x90ffff90 then
+  if checkMe == 0x909090ff then
     do
       entryAddr <- getMethodEntry eip 0
-      poke insn_ptr 0xe8 -- call opcode
-      -- it's a relative call, so we have to calculate the offset. why "+ 3"?
+      poke insn_ptr 0xe8 -- `call' opcode
+      -- it's a relative call, so we have to calculate the offset. why "+ 5"?
       -- (1) the whole insn is 5 bytes long
-      -- (2) begin of insn is displaced by 2 bytes
-      -- (3) offset is calculated wrt to the beginning of the next insn
-      poke imm_ptr (entryAddr - (eip + 3))
-      return (eip - 2)
+      -- (2) offset is calculated wrt to the beginning of the next insn
+      poke imm_ptr (entryAddr - (eip + 5))
+      return eip
     else error "staticCallHandler: something is wrong here. abort\n"
 
 staticFieldHandler :: CPtrdiff -> IO CPtrdiff