avr-libc-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-libc-dev] [bug #29774] prologue/epilogue stack pointer manipula


From: Galen Seitz
Subject: Re: [avr-libc-dev] [bug #29774] prologue/epilogue stack pointer manipulation not interrupt safe in XMega
Date: Wed, 05 May 2010 09:08:47 -0700
User-agent: Thunderbird 2.0.0.24 (X11/20100318)

Matthew Vernon wrote:
...

The actual code from the list file for my XMega project is shown below. Note
that 0x3F is the status register (including interrupt enable), and 0x3D with
0x3E are the stack pointer.

The status register is preserved, then interrupts are cleared. Half of the
stack is written, the status register is restored, then the other half of the
stack is written. On most architectures this is correct as one instruction can
safely execute after enabling interrupts (restore SREG) before an interrupt
can occur.


0001b082 <__epilogue_restores__>:
   ...
   1b0aa:       0f b6           in      r0, 0x3f        ; 63
   1b0ac:       f8 94           cli
   1b0ae:       de bf           out     0x3e, r29       ; 62
   1b0b0:       0f be           out     0x3f, r0        ; 63
   1b0b2:       cd bf           out     0x3d, r28       ; 61
   1b0b4:       ed 01           movw    r28, r26
   1b0b6:       08 95           ret


The XMega, however, can jump to an interrupt immediately after the status
register is restored and before the second half of the stack is written.
Therefore any interrupt code that uses the stack will potentially write to an
arbitrary memory location. In my application this results in stack corruption
and a function return to an arbitrary address.
...

This certainly looks like a problem. What version of gcc are you using, and what patches have been applied?

I have gcc 4.3.3 plus multiple patches, in particular gcc-4.3.3-xmega-v13. My gcc should closely match winavr20100110.

I'm not sure I'm looking in the correct place, but avr.c in my gcc build has the following code:

const char *
output_movhi (rtx insn, rtx operands[], int *l)
{
...
              if(AVR_XMEGA)
                {
                  *l = 2;
                  return (AS2 (out,__SP_L__,%A1)  CR_TAB
                          AS2 (out,__SP_H__,%B1));
                }
              else
                {
                  *l = 5;
                  return (AS2 (in,__tmp_reg__,__SREG__)  CR_TAB
                          "cli"                          CR_TAB
                          AS2 (out,__SP_H__,%B1)         CR_TAB
                          AS2 (out,__SREG__,__tmp_reg__) CR_TAB
                          AS2 (out,__SP_L__,%A1));


This suggests that xmega code should simply be restoring the stack pointer. (Note that on the xmega, when SPL is written all interrupts are disabled for up to four instructions or until SPH is also written.) However, when I look at the disassembly of the __prologue_saves__ and __epilogue_restores__ code for the xmega libgcc.a libraries, I see the code for the non-AVR_XMEGA path. The libgcc.a libraries from winavr20100110 are the same.

This is effectively the limit of my gcc debugging skills. It would be interesting to hear from someone who is more familiar with avr-gcc.

--
Galen Seitz
address@hidden




reply via email to

[Prev in Thread] Current Thread [Next in Thread]