clang generates incorrect gcov code when using -mno-red-zone flag
| Originator: | phil | ||
| Number: | rdar://12843084 | Date Originated: | 09-Dec-2012 08:55 PM |
| Status: | Closed | Resolved: | 19-Jun-2013 |
| Product: | Developer Tools | Product Version: | 4.6 |
| Classification: | Serious Bug | Reproducible: | Always |
Summary:
When compiling code with clang's -fprofile-arcs -ftest-coverage flags, the code generated for the automatically generated helper function __llvm_gcov_indirect_counter_increment ignores the -mno-red-zone flag.
Steps to Reproduce:
1. Create a source file redzone.c with the following content:
// BEGIN redzone.c
int hello(int a)
{
switch (a % 2)
{
case 0:
++a;
case 1:
a /= 2;
}
return a;
}
// END redzone.c
The exact content of the file is not of much relevance, we just need to get the compiler to generate a __llvm_gcov_indirect_counter_increment function.
2. Compile it using this command:
/Applications/Xcode46-DP3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -O0 -mno-red-zone -fprofile-arcs -ftest-coverage redzone.c -c
3. Inspect the disassembly of the function __llvm_gcov_indirect_counter_increment using the command:
otool -tV redzone.o -p ___llvm_gcov_indirect_counter_increment |less
Expected Results:
Due to the -mno-red-zone flag, no data should be stored below the %rsp stack pointer in the disassembly.
Actual Results:
The code uses 24 bytes of the red zone:
___llvm_gcov_indirect_counter_increment:
00000000000000f0 pushq %rbp
00000000000000f1 movq %rsp,%rbp ; note rsp is the same as rbp
00000000000000f4 movl (%rdi),%eax
00000000000000f6 cmpl $0xffffffff,%eax
00000000000000fb movq %rsi,0xf8(%rbp) ; RED ZONE
00000000000000ff movl %eax,0xf4(%rbp) ; RED ZONE
0000000000000102 je 0x00000137
0000000000000108 movl 0xf4(%rbp),%eax ; RED ZONE
000000000000010b movl %eax,%ecx
000000000000010d movq 0xf8(%rbp),%rdx ; RED ZONE
0000000000000111 movq (%rdx,%rcx,8),%rcx
0000000000000115 cmpq $_hello,%rcx
000000000000011c movq %rcx,0xe8(%rbp) ; RED ZONE
0000000000000120 je 0x00000137
0000000000000126 movq 0xe8(%rbp),%rax ; RED ZONE
000000000000012a movq (%rax),%rcx
000000000000012d addq $0x00000001,%rcx
0000000000000134 movq %rcx,(%rax)
0000000000000137 popq %rbp
0000000000000138 ret
0000000000000139 nopl _hello(%rax)
When running in an environment with no red zone on the stack, such as the OSX kernel, this code ends up crashing due to corruption of the pointers stored beyond the top of the stack.
Regression:
The versions of clang in the 4.5 Developer Tools and earlier do not exhibit this fault, although in the previous version the function was not generated as a local symbol.
Notes:
The generated function __llvm_gcov_init also appears to be affected, although it's less likely to cause a crash in that case, as it's so rarely executed. Other functions may also be affected?
Clang version:
Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
Target: x86_64-apple-darwin12.2.0
Thread model: posix
19-Feb-2013 06:14 PM Phillip Jordan:
The machine code generated by the compiler in the release version of the 4.6 developer tools is identical and thus still invalid.
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!