This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Gcc naked attribute leaves some trailing function prologue asm instructions

  I've the following implementation for a svc exception handler on a cortex-m0:

    int  __attribute__((naked))  
    sv_call_handler(uint32_t n, uint32_t arg1, uint32_t arg2, uint32_t arg3,  
                    uint32_t arg4, uint32_t arg5)
     {
          irq_off();


When I built it for cortex-m0 it looks like this:

       0x7a50 <sv_call_handler>        movs   r4, r0                                                                    
       0x7a52 <sv_call_handler+2>      str    r1, [r7, #12]                                                             
       0x7a54 <sv_call_handler+4>      str    r2, [r7, #8]                                                              
       0x7a56 <sv_call_handler+6>      str    r3, [r7, #4]                                                              
       0x7a58 <sv_call_handler+8>      bl     0x3194 <irq_off>

Resulting in a hard fault because of course, the value in R7 is 'undefined' and there is a high chance that it contains a value that isn't within the address range.

When I remove the naked attribute, the assembly makes much more sense:

       0x7a50 <sv_call_handler>        push   {r4, r5, r7, lr}                                                          
       0x7a52 <sv_call_handler+2>      sub    sp, #32                                                                   
       0x7a54 <sv_call_handler+4>      add    r7, sp, #8                                                                
       0x7a56 <sv_call_handler+6>      str    r0, [r7, #12]


I've used the naked attribute without issues before, so why does this happen now? Has it anything to do with the fact that the svc exception handler is a special case?

Parents
  • The GCC documentation states the following regarding use of __naked__ : "While using extended asm or a mixture of basic asm and C code may appear to work, they cannot be depended upon to work reliably and are not supported."

    In addition, it looks like you are trying to access values in r0-r3 that were present when the SVC instruction was executed, however, these should be being accessed via the stacked values rather than directly from the registers as any late arriving interrupt on the SVCall entry could result in the SVCall handler being tail-chained to with the register values not being the same as the stacked values; as such the first level SVCall handler should be of type "void func(void)", possibly __naked__, but then only with sufficient ASM to appropriately marshal SP, PSR and EXC_RETURN.

    Best regards

    Simon.

Reply
  • The GCC documentation states the following regarding use of __naked__ : "While using extended asm or a mixture of basic asm and C code may appear to work, they cannot be depended upon to work reliably and are not supported."

    In addition, it looks like you are trying to access values in r0-r3 that were present when the SVC instruction was executed, however, these should be being accessed via the stacked values rather than directly from the registers as any late arriving interrupt on the SVCall entry could result in the SVCall handler being tail-chained to with the register values not being the same as the stacked values; as such the first level SVCall handler should be of type "void func(void)", possibly __naked__, but then only with sufficient ASM to appropriately marshal SP, PSR and EXC_RETURN.

    Best regards

    Simon.

Children
No data