Fix win-x64 outgoing argument size calculation for PInvoke prolog helper#60050
Conversation
The win-x64 ABI requires allocating 32 bytes of outgoing argument stack space for every call, which can be used by callees. In the case where there are no calls in a function, there is no need to allocate that space. The JIT computes the required argument space during `fgSimpleLowering` by processing the IR and looking for call instructions, but also accounting for a few special cases where calls are not visible in the IR. One case was missing, leading to a zero-sized outgoing argument space even though a call was still generated. This can cause corruption in the caller stack frame. The case is where there are no explicit calls but the JIT is going to generate a PInvoke frame initialization helper call. This shouldn't happen, however, it occurs because the JIT eliminates a PInvoke that is statically dead code, but still generates the prolog setup code. A general solution would be to eliminate the PInvoke setup code if there are no remaining PInvokes in the function. The simple change made here is to ensure there is sufficient outgoing argument space for the PInvoke helper call if that will be generated. This was found by seeing test crashes due to stack corruption when building the CLR with the VC++ compiler `-O2` optimization switch, which stored data in the incoming argument stack space of the PInvoke helper function (with PR dotnet#59235). There are 5 SPMI diffs: 2 in coreclr tests (the ones that failed at runtime), 2 in libraries tests, and 1 in System.Net.Http.WinHttpChannelBinding:.ctor(SafeWinHttpHandle):this
|
Tagging subscribers to this area: @JulieLeeMSFT Issue DetailsThe win-x64 ABI requires allocating 32 bytes of outgoing argument A general solution would be to eliminate the PInvoke setup code if there This was found by seeing test crashes due to stack corruption when There are 5 SPMI diffs: 2 in coreclr tests (the ones that failed at runtime),
|
|
@dotnet/jit-contrib PTAL |
The win-x64 ABI requires allocating 32 bytes of outgoing argument
stack space for every call, which can be used by callees. In the case
where there are no calls in a function, there is no need to allocate
that space. The JIT computes the required argument space during
fgSimpleLoweringby processing the IR and looking for call instructions,but also accounting for a few special cases where calls are not visible
in the IR. One case was missing, leading to a zero-sized outgoing argument
space even though a call was still generated. This can cause corruption in the
caller stack frame. The case is where there are no explicit calls but the
JIT is going to generate a PInvoke frame initialization helper call. This
shouldn't happen, however, it occurs because the JIT eliminates a PInvoke
that is statically dead code, but still generates the prolog setup code.
A general solution would be to eliminate the PInvoke setup code if there
are no remaining PInvokes in the function. The simple change made here is
to ensure there is sufficient outgoing argument space for the PInvoke helper
call if that will be generated.
This was found by seeing test crashes due to stack corruption when
building the CLR with the VC++ compiler
-O2optimization switch, whichstored data in the incoming argument stack space of the PInvoke helper function
(with PR #59235).
There are 5 SPMI diffs: 2 in coreclr tests (the ones that failed at runtime),
2 in libraries tests, and 1 in
System.Net.Http.WinHttpChannelBinding:.ctor(SafeWinHttpHandle):this