[PATCH] D158084: [AArch64] Stack probing for function prologues
Momchil Velikov via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 16 07:38:21 PDT 2023
chill created this revision.
chill added reviewers: serge-sans-paille, jnspaulsson, bzEq, tnfchris, efriedma, jonpa, aemerson.
Herald added subscribers: ctetreau, hiraditya, kristof.beyls.
Herald added a project: All.
chill requested review of this revision.
Herald added subscribers: llvm-commits, wangpc.
Herald added a project: LLVM.
This adds code to AArch64 function prologues to protect against stack
clash attacks by probing (writing to) the stack at regular enough
intervals to ensure that the guard page cannot be skipped over.
The patch depends on and maintains the following invariants:
- Upon function entry the caller guarantees that it has probed the stack (e.g. performed a store) at some address `[sp, #N]`, where`0 <= N <= 1024`. This invariant comes from a requirement for compatibility with GCC.
- Any address range in the allocated stack, no smaller than `stack-probe-size` bytes contains at least one probe
The `stack-probe-size` is a function attribute that can be set by
a platform to correspond to the guard page size.
By default, the stack probe size is 4KiB, which is a safe default as
this is the smallest possible page size for AArch64. Linux uses a
64KiB guard for AArch64, so this can be overridden by the
`stack-probe-size` function attribute.
For small frames without a frame pointer (<= 240 bytes), no probes are
needed.
For larger frame sizes, LLVM always stores `x29` to the stack. This
serves as an implicit stack probe. Thus, while allocating stack
objects the compiler assumes that the stack has been probed at `[sp]`.
There are multiple probing sequences that can be emitted, depending on
the size of the stack allocation:
- A straight-line sequence of subtracts and stores, used when the allocation size is smaller than 5 guard pages.
- A loop allocating and probing one page size per iteration, plus at most a single probe to deal with the remainder, used when the allocation size is larger but still known at compile time.
- A loop which moves the SP down to the target value held in a register (or a loop, moving a scratch register to the target value help in SP), used when the allocation size is not known at compile-time, such as when allocating space for SVE values, or when over-aligning the stack. This is emitted in AArch64InstrInfo because it will also be used for dynamic allocas in a future patch.
- A single probe where the amount of stack adjustment is unknown, but is known to be less than or equal to a page size.
Co-authored-by: Oliver Stannard <oliver.stannard at linaro.org>
https://reviews.llvm.org/D158084
Files:
llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
llvm/lib/Target/AArch64/AArch64FrameLowering.h
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
llvm/lib/Target/AArch64/AArch64ISelLowering.h
llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
llvm/lib/Target/AArch64/AArch64InstrInfo.h
llvm/lib/Target/AArch64/AArch64InstrInfo.td
llvm/test/CodeGen/AArch64/stack-probing-64k.ll
llvm/test/CodeGen/AArch64/stack-probing-sve.ll
llvm/test/CodeGen/AArch64/stack-probing.ll
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D158084.550747.patch
Type: text/x-patch
Size: 77451 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230816/924b8ff0/attachment.bin>
More information about the llvm-commits
mailing list