llvm / llvm/llvm-project

Incorrect function epilogue when calling a function with the return_twice attribute on PowerPC

Open
#199,441 4 comments 0 reactions 1 assignee Claimed by @tonykuttai View on GitHub
backend:PowerPC miscompilation
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

LLVM emits an asymmetric prologue/epilogue for PowerPC when ASan instrumentation and a returns_twice call are present.
Based on information from the assembler in the https://godbolt.org/z/vz9zhdacW
The prologue dynamically realigns the stack:

```asm
clrlwi 0, 1, 27 ; d = old_sp & 31
subfic 0, 0, -576 ; r0 = -576 - d
stwux 1, 1, 0 ; sp = old_sp - 576 - d
...
mr 31, 1
```

but the epilogue restores SP using only the fixed frame size:

```asm
addi 31, 31, 576
mr 1, 31
lwz 0, 4(1)
mtlr 0
blr
```

So the restored SP becomes old_sp - d instead of old_sp. If d != 0, LR is loaded from the wrong stack slot and blr branches to garbage.

Asan instrumentation aligns the stack to the value specified in the "asan-realign-stack" flag, and changing it to the standard PowerPC ABI value of 16 resolves the issue (https://godbolt.org/z/xb71eh4Y5). However, this isn't a true fix, as it only masks the underlying issue with the function's epilogue.

I also assumed that "-mstack-alignment=32" should solve the problem, but the assembler is the same [with](https://godbolt.org/z/WejMornfe) or [without](https://godbolt.org/z/z1vMvs9M3) it. But that's probably a question for another ticket.

I found in llvm/lib/Target/PowerPC/PPCFrameLowering.cpp the code that was written 12 years ago:

```c++
// If this function contained a fastcc call and GuaranteedTailCallOpt is
// enabled (=> hasFastCall()==true) the fastcc call might contain a tail
// call which invalidates the stack pointer value in SP(0). So we use the
// value of R31 in this case. Similar situation exists with setjmp.
else if (FI->hasFastCall() || MF.exposesReturnsTwice())
```

I think it's worth looking into its relevance in relation to the fear of a corrupted backchain memory value pointed to by r1.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.