[LLVMdev] LLVM IR and Naked functions in C/C++
Jeffrey Lim
jeff at lim.com.au
Fri Nov 9 20:01:29 PST 2012
Hi,
I've recently been investigating problems with using naked functions in Clang where portions of the stack are overwritten in debug builds. This happens on all architectures I've tested (x86, x64, ARM) and is evident in the LLVM IR itself. With the svn builds of clang, there's an additional problem where undefined results are being introduced
First to show what I'm discussing:
test.cpp:
__attribute((noinline, naked)) int NakedTest(int value, int value2)
{
asm("");
}
Example using svn r167616 of clang/llvm:
clang -S test.cpp
.section __TEXT,__text,regular,pure_instructions
.globl __Z9NakedTestii
.align 4, 0x90
__Z9NakedTestii: ## @_Z9NakedTestii
.cfi_startproc
## BB#0: ## %entry
movl %edi, -8(%rbp)
movl %esi, -12(%rbp)
## InlineAsm Start
## InlineAsm End
ud2
.cfi_endproc
The first two highlighted lines are overwriting memory unexpected. The ud2 causes a runtime failure on all naked functions with a return type.
The same test.cpp compiled with Xcode 4.5.2's version of clang:
.section __TEXT,__text,regular,pure_instructions
.globl __Z9NakedTestii
.align 4, 0x90
__Z9NakedTestii: ## @_Z9NakedTestii
.cfi_startproc
## BB#0:
movl %edi, -8(%rbp)
movl %esi, -12(%rbp)
## InlineAsm Start
## InlineAsm End
movl -4(%rbp), %eax
ret
.cfi_endproc
I've developed a patch for clang that fixes these issues; however, upon review from Eli Friedman, one of the changes that I had to make was particularly concerning to him and he suggested that I post to this list for discussion -- it's a change required in VMCore/Verifier.cpp.
When we have a naked function, I'm always generating a ret void instruction in LLVM IR. This is even if the function has a signature that specifies a return type, but I need to do this so that the debug code generators don't insert any extra code to setup the return value. This fails the verifier (which complains that return type of function doesn't match return type instruction found), however, I believe that for naked functions (where all the body of the function would be written in "asm" sections), that this is actually what is necessary.
So I have a patch that checks for this (attached):
The question is: Am I doing anything that is fundamentally wrong? Will this cause any problems with the LLVM optimisers? Note that naked functions are also implicitly "noinline"
Thanks for your time,
Jeffrey Lim
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20121110/d9c01036/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: llvm.naked.patch
Type: application/octet-stream
Size: 1938 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20121110/d9c01036/attachment.obj>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20121110/d9c01036/attachment-0001.html>
More information about the llvm-dev
mailing list