> Overwriting function pointers gives code execution under shadow stacks
As you are probably aware, there are two kinds of CFI - forward-edge and backward-edge. Forward-edge CFI prevents tampered function pointers, vtables and such from being invoked. Whereas backward-edge CFI protects does the same for return addresses. Clang's and MSVC's (CFG) implementations of CFI only provide forward-edge protection, hence the need for shadow stacks. Without hardware support, shadow stacks can not be prevented from tampered, which is why Intel (CET) and AMD added shadow stacks.
> Mobile platforms are very memory sensitive
Agreed. I'd guess this applies to embedded too. But all things considered, I do hold the opinion that language-level memory safety is being overplayed a lot.
> Overwriting function pointers gives code execution under shadow stacks
As you are probably aware, there are two kinds of CFI - forward-edge and backward-edge. Forward-edge CFI prevents tampered function pointers, vtables and such from being invoked. Whereas backward-edge CFI protects does the same for return addresses. Clang's and MSVC's (CFG) implementations of CFI only provide forward-edge protection, hence the need for shadow stacks. Without hardware support, shadow stacks can not be prevented from tampered, which is why Intel (CET) and AMD added shadow stacks.
> Mobile platforms are very memory sensitive
Agreed. I'd guess this applies to embedded too. But all things considered, I do hold the opinion that language-level memory safety is being overplayed a lot.