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>