[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