Creating a mock is still better than not creating a mock to test against. With the mock you can create simulations, unit tests, coverage tests, static tests, formal verification.
Without mock you can just test on actual HW a few selected test scenarios you think of.
Emulation: The lack of qemu support for arm chips is mindboggling. avr/atmel is quite good in contrast. renode is far better.
You did not understand what i wrote. With hardware, its just damn difficult to get accurate mocks. If the mock is wrong, all tests relying on it are not meaningful.
If you ask me, QEMU doesn't even properly support emulating x86. Its just "good enough" to run common operating systems. You could try improving the support, maybe then you will realize how just damn difficult and undocumented this shit is, and you would understand why nobody wants to hear your crappy unit test evangelism.
Of course you have to patch qemu, gdb, renode and valgrind if something is missing. Eg the recent apple M1. But this is only needed for emulation, and we are talking simulation here.
That doesn't sound true at all tbh. I would imagine a huge amount of code is just generalized data structures and algorithms. I doubt many CVEs (<1%) rely on an accurate model of the underlying hardware.
Testing, coverage, static analysis, methodologies, etc... are a way to make prevent things from going wrong in the first place, defenses are here to protect you if things go wrong. We need both.
The article focuses only on the "defense" part, the development practices could make another article.
Note that testing and defenses can go together: test to make sure all paths are taken before shipping, and see if defenses trigger. Fuzzing in particular takes that approach.
Example: anything that directly accesses MMU or caches.
IO, assembly and interrupts are much harder.
There's two ways I can interpret "the unit test".
1) "How would you create a mock object for modifying the memory layout of the code being tested?" That's just a routine that shuffles around some bytes. Or marks parts of the address space to fault so it can simulate the contents.
2) "How would you create a mock object for modifying the memory layout of the code performing the test?" That wouldn't be a test. The code performing the test isn't inside its own simulation.
The MMU is just a simple 3way array lookup, as a Unicode table.