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
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