While this approach is most definitely functional, it comes with a number of caveats that make it sub-optimal for any sort of large-scale deployment. The following considerations are by no means all-encompassing, but some of the more important ones have been enumerated below:
- Unsafe modification of PTEs
It is not safe to modify PTEs without acquiring certain locks. Unfortunately, these locks are not exported and are therefore inaccessible to third party drivers.
- Large amount of overhead
The overhead associated with having to take a page fault and pass the exception on to the be handled by user-mode is substantial. Memory access time with respect to the application could jump from nanoseconds to micro or even milli seconds.
- Requires the use of a disassembler
Since this approach relies on mirroring memory references from one virtual address to another, a disassembler has to be used to figure out which registers need to be modified with the mirrored address. Any time a disassembler is needed is an indication that things are getting fairly complicated.
- Cannot track memory references to all addresses
The fact that this approach relies on locking physical pages prevents it from feasibly tracking all memory references. In addition, because the thread stack is required to be valid in order to dispatch exceptions, it's not possible to track reads and writes to thread stacks using this approach.