[LLVMbugs] [Bug 18791] New: Naked attribute: clang emits extraneous, stack-altering code for naked functions that have a parameter.
bugzilla-daemon at llvm.org
bugzilla-daemon at llvm.org
Mon Feb 10 03:26:46 PST 2014
http://llvm.org/bugs/show_bug.cgi?id=18791
Bug ID: 18791
Summary: Naked attribute: clang emits extraneous,
stack-altering code for naked functions that have a
parameter.
Product: clang
Version: 3.4
Hardware: PC
OS: Windows NT
Status: NEW
Severity: normal
Priority: P
Component: -New Bugs
Assignee: unassignedclangbugs at nondot.org
Reporter: carl.william at wittenstein.co.uk
CC: llvmbugs at cs.uiuc.edu
Classification: Unclassified
clang/LLVM emits extra register- and stack-altering code before and after body
of "naked" function, when the function is declared with a parameter.
It also emits extra code when the function is declared with a return value, and
in all cases emits a return after the function body (the return is usually
harmless, though, likewise the extra code in the return value case.)
It looks as if part of the normal function stack frame setup/take-down is being
generated, but the code produced in the function-having-a-parameter case is
problematic as it overwrites part of the in-use stack (without first advancing
the stack pointer).
I made some attempt to elicit different behaviour with different syntax and
different command line parameters (e.g. turning off debug with -g0) but
couldn't get rid of the erroneous object code.
It appears to do the same with other targets, e.g. ARM7 and x86.
For comparison, a recent arm-none-eabi-gcc appears to emit nothing but the body
of the __asm, in all cases without a return value, and a single register copy
after the body of the __asm in the cases that do have a return value.
The only truly problematic bit of extra code is the stack write before the
__asm body; everything after the __asm body is usually just dead code because
the body of a naked function may be expected to do its own return. The register
write before the body is unexpected, but there are few circumstances with the
ARM ABI at any rate, where a write to R1 is an issue.
With many parameters, however, especially beyond the four params that will
typically be passed in simple registers, the degree of stack and register
corruption is much worse. See extra example, below.
Work-around:
------------
Code parametrized naked functions in assembly or using inline __asm() semantics
directly in macros.
Example code that illustrates the issue:
---------------------------------------
naked_test.c
------------
__attribute__((naked)) void void_foo( void )
{
__asm volatile ( " nop " );
}
__attribute__((naked)) int retval_foo( void )
{
__asm volatile ( " nop " );
}
__attribute__((naked)) void param_foo( int bar )
{
__asm volatile ( " nop " );
}
__attribute__((naked)) int retval_param_foo( int bar )
{
__asm volatile ( " nop " );
}
Compiled with
-------------
clang -mcpu=cortex-m3 --target=thumbv7m--none-eabi -mthumb -S naked_test.c -o
naked_test.s
Code generated (with comments added)
------------------------------------
.syntax unified
.cpu cortex-m3
.eabi_attribute 6, 10
.eabi_attribute 7, 77
.eabi_attribute 8, 0
.eabi_attribute 9, 2
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 44, 2
.file "naked_test.c"
.text
.globl void_foo
.align 2
.type void_foo,%function
.code 16
.thumb_func
void_foo: /* Naked except extraneous/harmless bx lr */
@APP
nop
@NO_APP
bx lr
.Ltmp0:
.size void_foo, .Ltmp0-void_foo
.globl retval_foo
.align 2
.type retval_foo,%function
.code 16
.thumb_func
retval_foo:
@APP
nop
@NO_APP
ldr r0, [sp] /* extra ldr will clobber return val */
bx lr /* if __asm code doesn't return, but */
.Ltmp1: /* this is mostly harmless */
.size retval_foo, .Ltmp1-retval_foo
.globl param_foo
.align 2
.type param_foo,%function
.code 16
.thumb_func
param_foo:
mov r1, r0 /* clobbers R1 with R0 param */
str r0, [sp, #4] /* Bad: clobbering in-use stack */
@APP
nop
@NO_APP
str r1, [sp] /* clobbering stack some more if __asm */
bx lr /* doesn't do its own return. */
.Ltmp2:
.size param_foo, .Ltmp2-param_foo
.globl retval_param_foo
.align 2
.type retval_param_foo,%function
.code 16
.thumb_func
retval_param_foo: /* combines retval and param cases */
mov r1, r0
str r0, [sp, #4]
@APP
nop
@NO_APP
ldr r0, [sp, #8]
str r1, [sp]
bx lr
.Ltmp3:
.size retval_param_foo, .Ltmp3-retval_param_foo
.ident "clang version 3.4 (198054)"
Extra example illustrating case with many parameters
----------------------------------------------------
__attribute__((naked)) void many_param_foo( int bar1, int bar2, int bar3, int
bar4, int bar5 )
{
__asm volatile ( " nop " );
}
.globl many_param_foo
.align 2
.type many_param_foo,%function
.code 16
.thumb_func
many_param_foo:
ldr.w r12, [sp, #36]
mov lr, r3
mov r4, r2
mov r5, r1
mov r6, r0
str r0, [sp, #32]
str r1, [sp, #28]
str r2, [sp, #24]
str r3, [sp, #20]
str.w r12, [sp, #16]
@APP
nop
@NO_APP
str.w lr, [sp, #12]
str r4, [sp, #8]
str r5, [sp, #4]
str r6, [sp]
bx lr
.Ltmp4:
.size many_param_foo, .Ltmp4-many_param_foo
.ident "clang version 3.4 (198054)"
--
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/20140210/b1a970f9/attachment.html>
More information about the llvm-bugs
mailing list