From 3c1c1355bc77bf53846255a628416aa36a730e23 Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Thu, 2 Aug 2012 21:37:24 +0200 Subject: [PATCH] staticcall trap: use different magic sequence 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 | 7 +++---- Mate/X86TrapHandling.hs | 21 ++++++++++----------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/Mate/X86CodeGen.hs b/Mate/X86CodeGen.hs index 6def8de..710b5b6 100644 --- a/Mate/X86CodeGen.hs +++ b/Mate/X86CodeGen.hs @@ -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 diff --git a/Mate/X86TrapHandling.hs b/Mate/X86TrapHandling.hs index 6ec0124..f89e2b8 100644 --- a/Mate/X86TrapHandling.hs +++ b/Mate/X86TrapHandling.hs @@ -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 -- 2.25.1