Dynamic stack frame size support #23481
Description
Problem
When using dynamic stack frames, r11 is exposed as the stack pointer. The stack is fully descending, so sub r11, N can be used to grow it, and add r11, N to shrink it. Those instructions are special-cased by the interpreter and jit to resize the stack. No other operations are allowed on the stack register.
The stack pointer is allowed to overflow. In real programs, it's almost impossible to overflow since programs are metered and we enforce a max call depth. In fringe programs that (intentionally?) do overflow, EbpfError::AccessViolation is returned by MemoryRegion::map() once the overflown stack pointer is accessed. I opted for this since I think it's the best tradeoff for jitted programs (the BPF stack is separate from the jit stack so overflows won't mess with the jit), but happy to do explicit overflow checking if anyone feels strongly about this (although I'm not sure what the benefit would be).
At the moment config.max_call_depth is still enforced regardless of whether fixed or dynamic frames are in use, we might want to change that.
Proposed Solution
Dynamic frames are turned on if the input ELF is flagged as EF_SBF_V2 (see anza-xyz/llvm-project#26) and config.dynamic_stack_frames=true. This means that a feature gate can be used in the monorepo to set dynamic_stack_frames=false to disable the feature entirely.
Addressed in:
anza-xyz/llvm-project#26
solana-labs/rbpf#274