[llvm-bugs] [Bug 49130] New: [x86] Tail merging two variadic calls produces incorrect CFI
via llvm-bugs
llvm-bugs at lists.llvm.org
Wed Feb 10 14:23:21 PST 2021
https://bugs.llvm.org/show_bug.cgi?id=49130
Bug ID: 49130
Summary: [x86] Tail merging two variadic calls produces
incorrect CFI
Product: libraries
Version: trunk
Hardware: PC
OS: All
Status: NEW
Severity: enhancement
Priority: P
Component: Backend: X86
Assignee: unassignedbugs at nondot.org
Reporter: rnk at google.com
CC: craig.topper at gmail.com, llvm-bugs at lists.llvm.org,
llvm-dev at redking.me.uk, pengfei.wang at intel.com,
spatel+llvm at rotateright.com
This comes up in the Linux kernel, as reported here:
https://github.com/ClangBuiltLinux/linux/issues/612
https://lkml.org/lkml/2019/7/16/759
Consider:
$ cat t.c
int a, b;
void mypanic(int, ...) __attribute__((noreturn));
void imbalanced() {
if (a)
mypanic(0, 0, 0, 0, 0, 0, a);
if (b)
mypanic(0, 0, 0, 0, 0, 0, a, 0);
}
$ clang -Os t.c -S -o -
.text
.file "t.c"
.globl imbalanced # -- Begin function imbalanced
.type imbalanced, at function
imbalanced: # @imbalanced
.cfi_startproc
# %bb.0: # %entry
pushq %rax
.cfi_def_cfa_offset 16
movl a(%rip), %r10d
testl %r10d, %r10d
jne .LBB0_3
# %bb.1: # %if.end
cmpl $0, b(%rip)
jne .LBB0_5
# %bb.2: # %if.end3
popq %rax
.cfi_def_cfa_offset 8
retq
.LBB0_3: # %if.then
.cfi_def_cfa_offset 16
subq $8, %rsp
.cfi_adjust_cfa_offset 8
xorl %edi, %edi
xorl %esi, %esi
xorl %edx, %edx
xorl %ecx, %ecx
xorl %r8d, %r8d
xorl %r9d, %r9d
xorl %eax, %eax
jmp .LBB0_4
.LBB0_5: # %if.then2
.cfi_def_cfa_offset 16
xorl %r10d, %r10d
xorl %edi, %edi
xorl %esi, %esi
xorl %edx, %edx
xorl %ecx, %ecx
xorl %r8d, %r8d
xorl %r9d, %r9d
xorl %eax, %eax
pushq %r10
.cfi_adjust_cfa_offset 8
.LBB0_4: # %if.then
pushq %r10
.cfi_adjust_cfa_offset 8
callq mypanic
.Lfunc_end0:
.size imbalanced, .Lfunc_end0-imbalanced
.cfi_endproc
# -- End function
What we have here is two calls to mypanic, one with 7 args, one with 8. One
call does two pushes, and the other does one. If you interpret the .cfi_*
directives as written, they are only correct if the program executes the second
'if' branch, not the first. If the program executes the first 'if' and attempts
to unwind the stack, the wrong return address will be used.
Perhaps the CFI inserter pass could fix this by adding the full cfa offset to
each .cfi_adjust_cfa_offset instruction, or by adding some kind of no-op marker
instruction to the end of the MBB that encodes the cfa. This would prevent tail
merging from considering these blocks to be identical.
--
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20210210/109c085a/attachment.html>
More information about the llvm-bugs
mailing list