- The protection will overwrite the next instruction to obscure it
- The protection will clear all trace of itself up to and including the last instruction
Implementing stage 2 in a JIT however is not straightforward, particularly for the ARM where self-modifying code requires the cache and pipeline to be flushed. You're in catch 22, where you want the next instruction to be in the pipeline but also have to flush it and the cache, to comply with a Harvard cache implementation.
Full stage 2 implementation requires:
- The Abort handler needs to take a copy of the instruction at PC+4 and JIT PC+4 (coded in 2.51g)
- The JIT Abort handler needs to check on exit if the next instruction has been overwritten and reinstate it if necessary (coded in 2.51g)
- If the instruction at PC-4 has yet to be encoded it needs encoding and executing before being replaced
- The JIT core needs to check if a pipelined instruction overwrite is pending and correct it once the pipelined instruction has been executed
- STR Rx, [PC, #-4] will be in a codelet and won't be caught by the Abort handler by default. The Abort handler will need to check if the Abort occurred in a codelet and then check if the original instruction address is PC-4
- Allowing the original instruction to be overwritten, but leave the encoded instruction, then put a Hypervisor entry instruction at PC+8 and add PC to a pipeline replacement table. When the JIT is entered, it needs to write a Hypervisor instruction to the pipelined address.
This will need to take pipelined BL / B instructions into account and put the Hypervisor instruction at the branch address instead of PC+8.
- F10018 - Arcade 3
F10067 - Carnage Inc.
F10071 - Cataclysm
F10125 - Drifter (confirmed to work with points 1/2 implemented)
F10127 - Drop Ship
F10129 - The Dungeon
F10130 - Elite
F10164 - Formula Two Thousand
F10166 - F.R.E.D. (needs point 6)
F10274 - Pandora's Box
F10361 - TACTIC