[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